teecup/app/main.py
Erol Haagenrud 3270d044de Migrasjonen er kjørt, og jeg har fortsatt helt til et komplett, verifisert API-lag.
Underveis fant og fikset jeg et reelt hull: round_participant manglet kolonner for selve rating-tallene (kun tee-navnet var lagret) — løst med migrasjon 021, kjørt mot ekte database sammen med resten.

Bygget og rullet ut:

app/routers/rounds.py — opprett/liste/hent/slett runde, legg til/fjern gjestedeltakere, registrer statistikk hull for hull, og en fullfør-endepunkt som kjører hele kjeden (Adjusted Gross Score → Score Differential → tellende-vurdering).
26 scratch-sjekker grønt, pluss en egen test mot den ekte kjørende teeoff-tjenesten som bekreftet at live-oppslaget fungerer nøyaktig som tiltenkt (ingen bane-kopi skrives noe sted).
Begge migrasjoner + ny kode er nå live mot ekte teecup_db/teecup_api. teeoff.no upåvirket.
Jeg la også inn /rounds og /personal-courses i frontendens proxy-oppsett proaktivt, siden prosjektet har blitt bitt av glemte proxy-ruter før — ikke deployet ennå, tas med neste gang frontend faktisk bygges.

Notatet om slaglengde-måling og avstand-til-punkter-på-banen er lagret i CLAUDE.md og FEATURE_BACKLOG.md, med en tydelig flagget avhengighet: dette krever geografiske/GPS-data som ingen nåværende kilde (verken teeoff eller den nye banekatalogen) har.
2026-07-22 11:31:08 +02:00

61 lines
1.5 KiB
Python

"""
TeeCup API.
App-factory + livssyklus. All forretningslogikk ligger i app/routers/ — hver
rute der følger samme mønster: Depends(get_authorized_org) verifiserer
medlemskap, org_connection(organization_id) setter RLS-konteksten lokalt for
transaksjonen. Se ARCHITECTURE_DECISIONS.md (ADR-001…014) for reglene bak.
Kjøres i app-containeren (FastAPI + asyncpg + uvicorn):
uvicorn app.main:app --host 0.0.0.0 --port 8000
"""
from contextlib import asynccontextmanager
from fastapi import FastAPI
from .db import init_pool, close_pool
from .routers import (
auth,
courses,
matches,
messaging,
organizations,
players,
registration,
rounds,
scoring,
tournaments,
)
from . import storage
@asynccontextmanager
async def lifespan(app: FastAPI):
await init_pool()
await storage.ensure_bucket()
try:
yield
finally:
await close_pool()
app = FastAPI(title="TeeCup API", lifespan=lifespan)
app.include_router(auth.router)
app.include_router(organizations.router)
app.include_router(players.router)
app.include_router(courses.router)
app.include_router(tournaments.router)
app.include_router(matches.router)
app.include_router(scoring.router)
app.include_router(registration.router)
app.include_router(registration.org_router)
app.include_router(messaging.router)
app.include_router(messaging.public_router)
app.include_router(rounds.router)
@app.get("/health")
async def health() -> dict[str, str]:
return {"status": "ok"}