""" ADR-060: samme optimistiske versjonssjekk som round_hole (ADR-057) fikk, nå for org-turneringenes match-scoring (hole_score/match_hole_result, app/routers/scoring.py). Kaller de faktiske router-funksjonene direkte -- samme kodesti som produksjon, ikke en SQL-gjenimplementering. Autorisasjon: testbrukeren er satt som org-EIER (organization_membership role='owner'), som tilfredsstiller user_is_match_participant sin is_org_admin-fallback (team_authz.py) uten å måtte bygge ut hele player/team_roster/match_participant-kjeden for HVER test -- kun test_hole_score_individual_ball_participant_path bygger den fulle kjeden, siden DEN grenen i submit_hole_score krever en ekte match_participant-rad å slå opp uavhengig av org-admin-status. """ import pytest from fastapi import HTTPException from app import db as app_db from app.auth import CurrentUser from app.routers.scoring import ( HoleResultCreate, HoleScoreCreate, submit_hole_result, submit_hole_score, ) from tests.conftest import ( add_membership, create_course, create_match, create_match_participant, create_org, create_player, create_session, create_team, create_team_roster, create_tee, create_tournament, create_user, ) async def _setup_match(scoring_mode: str = "stroke", format_: str = "foursome"): org_id = await create_org() user_id = await create_user() await add_membership(org_id, user_id, role="owner") tournament_id = await create_tournament(org_id) team_a = await create_team(org_id, tournament_id) team_b = await create_team(org_id, tournament_id) course_id = await create_course(org_id) session_id = await create_session( org_id, tournament_id, course_id, format=format_, scoring_mode=scoring_mode ) match_id = await create_match(org_id, session_id, team_a, team_b) return org_id, user_id, match_id, team_a, team_b async def test_hole_score_shared_ball_succeeds_and_increments_version(pool): org_id, user_id, match_id, _, _ = await _setup_match() user = CurrentUser(user_id=user_id) first = await submit_hole_score( match_id, HoleScoreCreate(team_side="a", hole_number=1, gross_strokes=5, expected_version=None), org_id, user=user, ) assert first.version == 1 assert first.gross_strokes == 5 second = await submit_hole_score( match_id, HoleScoreCreate(team_side="a", hole_number=1, gross_strokes=4, expected_version=1), org_id, user=user, ) assert second.version == 2 assert second.gross_strokes == 4 async def test_hole_score_stale_version_is_409(pool): org_id, user_id, match_id, _, _ = await _setup_match() user = CurrentUser(user_id=user_id) await submit_hole_score( match_id, HoleScoreCreate(team_side="a", hole_number=1, gross_strokes=5, expected_version=None), org_id, user=user, ) # "Enhet 2" hadde OGSÅ lest versjon 1 (før dette skjedde), og prøver nå # å skrive med en versjon som allerede er forbigått. with pytest.raises(HTTPException) as exc_info: await submit_hole_score( match_id, HoleScoreCreate(team_side="a", hole_number=1, gross_strokes=6, expected_version=99), org_id, user=user, ) assert exc_info.value.status_code == 409 assert exc_info.value.detail["code"] == "STALE_VERSION" # Og bekreft at den avviste skrivingen faktisk IKKE ble lagret. async with app_db.org_connection(org_id) as conn: row = await conn.fetchrow( "SELECT gross_strokes, version FROM hole_score WHERE match_id = $1 AND hole_number = 1", match_id ) assert row["gross_strokes"] == 5 assert row["version"] == 1 async def test_hole_score_expected_version_none_bypasses_check(pool): org_id, user_id, match_id, _, _ = await _setup_match() user = CurrentUser(user_id=user_id) await submit_hole_score( match_id, HoleScoreCreate(team_side="a", hole_number=1, gross_strokes=5, expected_version=None), org_id, user=user, ) out = await submit_hole_score( match_id, HoleScoreCreate(team_side="a", hole_number=1, gross_strokes=7, expected_version=None), org_id, user=user, ) assert out.gross_strokes == 7 assert out.version == 2 async def test_hole_score_individual_ball_participant_path(pool): """Den ANDRE ON CONFLICT-grenen i submit_hole_score (match_participant_id satt) -- egen kode, egen WHERE-versjonssjekk, verdt å dekke separat fra delt-ball-testene over. Krever en ekte match_participant-rad (kylling- og-egg: user_is_match_participant sin participant-sjekk er uavhengig av org-admin-fallbacken for AKKURAT denne oppslags-grenen i submit_hole_score, se linje ~534 i scoring.py).""" org_id, user_id, match_id, team_a, _ = await _setup_match(format_="singles") user = CurrentUser(user_id=user_id) course_id = await create_course(org_id) tee_id = await create_tee(org_id, course_id) player_id = await create_player(org_id, user_id=user_id) roster_id = await create_team_roster(org_id, team_a, player_id) participant_id = await create_match_participant(org_id, match_id, "a", roster_id, tee_id) first = await submit_hole_score( match_id, HoleScoreCreate( team_side="a", match_participant_id=participant_id, hole_number=1, gross_strokes=4, expected_version=None, ), org_id, user=user, ) assert first.version == 1 with pytest.raises(HTTPException) as exc_info: await submit_hole_score( match_id, HoleScoreCreate( team_side="a", match_participant_id=participant_id, hole_number=1, gross_strokes=9, expected_version=99, ), org_id, user=user, ) assert exc_info.value.status_code == 409 assert exc_info.value.detail["code"] == "STALE_VERSION" async def test_hole_result_succeeds_and_increments_version(pool): org_id, user_id, match_id, _, _ = await _setup_match(scoring_mode="hole_result") user = CurrentUser(user_id=user_id) first = await submit_hole_result( match_id, HoleResultCreate(hole_number=1, winning_side="a", expected_version=None), org_id, user=user ) assert first.version == 1 assert first.winning_side == "a" second = await submit_hole_result( match_id, HoleResultCreate(hole_number=1, winning_side="b", expected_version=1), org_id, user=user ) assert second.version == 2 assert second.winning_side == "b" async def test_hole_result_stale_version_is_409(pool): org_id, user_id, match_id, _, _ = await _setup_match(scoring_mode="hole_result") user = CurrentUser(user_id=user_id) await submit_hole_result( match_id, HoleResultCreate(hole_number=1, winning_side="a", expected_version=None), org_id, user=user ) with pytest.raises(HTTPException) as exc_info: await submit_hole_result( match_id, HoleResultCreate(hole_number=1, winning_side="b", expected_version=99), org_id, user=user ) assert exc_info.value.status_code == 409 assert exc_info.value.detail["code"] == "STALE_VERSION"