""" Utslagsgrupper (migrasjon 084, 2026-08-18, ADR-088): hvem spiller med hvem, klokka når -- for individuelle turneringer. Bruker: "Jeg må jo kunne bulksjekke hvem som skal spille fra hvor, med hvem, klokka når?" Design bekreftet: tradisjonelt utslag (samme starthull, staggerte klokkeslett med fast intervall), manuell gruppesammensetning med et forslag å justere, fast gruppestørrelse. """ from app.routers.individual_tournaments import ( RoundGroupIn, SaveRoundGroupsIn, SuggestGroupsIn, TournamentRoundUpdate, list_round_groups, save_round_groups, suggest_round_groups, update_round, ) from tests.conftest import ( create_org, create_course, create_player, create_tee, create_tournament, create_tournament_participant, create_tournament_round, create_tournament_round_participant, ) import app.db as app_db async def _setup(org_id, n_players=5): tournament_id = await create_tournament(org_id, name="Gruppe-turnering") course_id = await create_course(org_id, name="Gruppe Links") tee_id = await create_tee(org_id, course_id) async with app_db.org_connection(org_id) as conn: await conn.execute( "UPDATE tournament SET format_type = 'individual', scoring_method = 'stroke_gross' WHERE id = $1", tournament_id, ) round_id = await create_tournament_round(org_id, tournament_id, course_id, sequence=1) rp_ids = [] for i in range(n_players): player_id = await create_player(org_id, display_name=f"Spiller {i:02d}") tp_id = await create_tournament_participant(org_id, tournament_id, player_id) rp_ids.append(await create_tournament_round_participant(org_id, round_id, tp_id, tee_id)) return tournament_id, round_id, rp_ids async def test_update_round_sets_scheduling_fields(pool): org_id = await create_org() tournament_id, round_id, _ = await _setup(org_id, n_players=1) updated = await update_round( tournament_id, round_id, TournamentRoundUpdate(scheduled_at="2026-08-19T10:00:00", tee_interval_minutes=10, start_hole=1), organization_id=org_id, ) assert updated.tee_interval_minutes == 10 assert updated.start_hole == 1 assert "2026-08-19" in (updated.scheduled_at or "") async def test_suggest_round_groups_chunks_by_size_and_computes_tee_times_without_saving(pool): org_id = await create_org() tournament_id, round_id, rp_ids = await _setup(org_id, n_players=5) await update_round( tournament_id, round_id, TournamentRoundUpdate(scheduled_at="2026-08-19T10:00:00", tee_interval_minutes=10), organization_id=org_id, ) suggestion = await suggest_round_groups( tournament_id, round_id, SuggestGroupsIn(group_size=2), organization_id=org_id ) assert [len(g.participants) for g in suggestion.groups] == [2, 2, 1] assert [g.sequence for g in suggestion.groups] == [1, 2, 3] assert suggestion.groups[0].tee_time is not None and "10:00" in suggestion.groups[0].tee_time assert suggestion.groups[1].tee_time is not None and "10:10" in suggestion.groups[1].tee_time assert suggestion.groups[2].tee_time is not None and "10:20" in suggestion.groups[2].tee_time # Alle grupper i forslaget er usaved (id=None). assert all(g.id is None for g in suggestion.groups) # Ingenting skal faktisk ha blitt lagret av selve forslaget. saved = await list_round_groups(tournament_id, round_id, organization_id=org_id) assert saved.groups == [] assert len(saved.ungrouped) == 5 async def test_save_round_groups_persists_and_fully_replaces_previous(pool): org_id = await create_org() tournament_id, round_id, rp_ids = await _setup(org_id, n_players=4) await update_round( tournament_id, round_id, TournamentRoundUpdate(scheduled_at="2026-08-19T10:00:00", tee_interval_minutes=10), organization_id=org_id, ) first = await save_round_groups( tournament_id, round_id, SaveRoundGroupsIn(groups=[ RoundGroupIn(sequence=1, round_participant_ids=[rp_ids[0], rp_ids[1]]), RoundGroupIn(sequence=2, round_participant_ids=[rp_ids[2], rp_ids[3]]), ]), organization_id=org_id, ) assert len(first.groups) == 2 assert len(first.ungrouped) == 0 # Lagre på nytt med en HELT ANNEN sammensetning -- skal erstatte, ikke legge til. second = await save_round_groups( tournament_id, round_id, SaveRoundGroupsIn(groups=[ RoundGroupIn(sequence=1, round_participant_ids=[rp_ids[0], rp_ids[2], rp_ids[3]]), ]), organization_id=org_id, ) assert len(second.groups) == 1 assert len(second.groups[0].participants) == 3 assert len(second.ungrouped) == 1 assert second.ungrouped[0].round_participant_id == rp_ids[1] async with app_db.org_connection(org_id) as conn: group_count = await conn.fetchval( "SELECT count(*) FROM tournament_round_group WHERE tournament_round_id = $1", round_id ) assert group_count == 1 # den gamle gruppen faktisk slettet, ikke bare "løsrevet" async def test_save_round_groups_leaves_unlisted_participants_ungrouped(pool): org_id = await create_org() tournament_id, round_id, rp_ids = await _setup(org_id, n_players=3) result = await save_round_groups( tournament_id, round_id, SaveRoundGroupsIn(groups=[RoundGroupIn(sequence=1, round_participant_ids=[rp_ids[0]])]), organization_id=org_id, ) assert len(result.groups) == 1 assert {p.round_participant_id for p in result.ungrouped} == {rp_ids[1], rp_ids[2]} async def test_group_tee_time_override_wins_over_computed(pool): org_id = await create_org() tournament_id, round_id, rp_ids = await _setup(org_id, n_players=2) await update_round( tournament_id, round_id, TournamentRoundUpdate(scheduled_at="2026-08-19T10:00:00", tee_interval_minutes=10), organization_id=org_id, ) result = await save_round_groups( tournament_id, round_id, SaveRoundGroupsIn(groups=[ RoundGroupIn(sequence=1, tee_time_override="2026-08-19T09:15:00", round_participant_ids=rp_ids), ]), organization_id=org_id, ) assert result.groups[0].tee_time is not None assert "09:15" in result.groups[0].tee_time # override, IKKE den utledede 10:00