""" Egendefinerte baner på organisasjonsnivå (ADR-001: gjenbrukbar på tvers av turneringer, samme mønster som players.py). `course.source = 'custom'` er den eneste veien inn her -- 'official' (ekte teeoff-baner via ADR-004 sitt planlagte, lesende API) er fortsatt kun vedtatt, ikke bygget (se FEATURE_BACKLOG.md), og krever uansett `external_course_ref` satt (skjemaets CHECK-constraint), som ingen klient kan oppgi meningsfullt ennå. Denne runden dekker KUN det organisatoren trenger for å opprette en økt: en bane ved navn, ingen hull-/tee-/rating-detaljer ennå (session-motoren bruker foreløpig kun course_id som fremmednøkkel, ikke banens innhold). """ from fastapi import APIRouter, Depends from ..auth import get_authorized_org from ..db import org_connection from ..errors import translate_db_errors from pydantic import BaseModel, Field router = APIRouter() class CourseCreate(BaseModel): name: str = Field(min_length=1, max_length=200) class Course(BaseModel): id: str name: str source: str _COURSE_COLUMNS = "id::text, name, source::text AS source" @router.get("/orgs/{organization_id}/courses", response_model=list[Course]) async def list_courses( organization_id: str = Depends(get_authorized_org), ) -> list[Course]: async with org_connection(organization_id) as conn: rows = await conn.fetch(f"SELECT {_COURSE_COLUMNS} FROM course ORDER BY name") return [Course(**dict(r)) for r in rows] @router.post("/orgs/{organization_id}/courses", response_model=Course, status_code=201) async def create_course( body: CourseCreate, organization_id: str = Depends(get_authorized_org), ) -> Course: async with org_connection(organization_id) as conn, translate_db_errors(): row = await conn.fetchrow( f""" INSERT INTO course (organization_id, name, source) VALUES ($1, $2, 'custom') RETURNING {_COURSE_COLUMNS} """, organization_id, body.name, ) return Course(**dict(row))