from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from contextlib import asynccontextmanager import asyncpg import json from datetime import date, datetime DB_URL = "postgresql://teeoff_admin:teeoff_secret_password@db:5432/teeoff" @asynccontextmanager async def lifespan(app: FastAPI): try: app.state.pool = await asyncpg.create_pool(DB_URL, min_size=5, max_size=20) print("✅ Database tilkoblet og pool opprettet") except Exception as e: print(f"❌ Databasefeil: {e}") raise e yield await app.state.pool.close() app = FastAPI(title="TeeOff API v2.4", lifespan=lifespan) app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) def format_row(row): if row is None: return None d = dict(row) # 1. Dato-håndtering for key in ['status_updated_at', 'created_at']: if isinstance(d.get(key), (date, datetime)): d[key] = d[key].isoformat() # 2. Garanter riktige datatyper (Vaskeliste) list_fields = ['course_statuses', 'courses', 'gallery', 'greenfee', 'faqs', 'shotzoom', 'social_links', 'holes'] dict_fields = ['amenities', 'vtg', 'nsg_data', 'golfamore_data'] for field in list_fields: if field in d: if d[field] is None: d[field] = [] elif isinstance(d[field], str): try: d[field] = json.loads(d[field]) except: d[field] = [] for field in dict_fields: if field in d: if d[field] is None: d[field] = {} elif isinstance(d[field], str): try: d[field] = json.loads(d[field]) except: d[field] = {} return d @app.get("/api/facilities") async def get_facilities(): async with app.state.pool.acquire() as conn: rows = await conn.fetch(""" SELECT f.*, ( SELECT jsonb_agg(cs) FROM ( SELECT name, status FROM courses WHERE facility_id = f.id AND status != 'finnes_ingen_bane_to' ORDER BY is_main_course DESC, id ASC ) cs ) as course_statuses FROM facilities f ORDER BY f.name ASC """) return [format_row(row) for row in rows] @app.get("/api/facilities/{slug}") async def get_facility(slug: str): async with app.state.pool.acquire() as conn: row = await conn.fetchrow(""" SELECT f.*, ( SELECT jsonb_agg(c_data) FROM ( SELECT c.*, ( SELECT jsonb_agg(h_data ORDER BY h_data.hole_number ASC) FROM (SELECT * FROM holes WHERE course_id = c.id) h_data ) as holes FROM courses c WHERE c.facility_id = f.id AND (c.is_main_course = true OR (c.status NOT IN ('finnes_ingen_bane_to', 'ukjent'))) ORDER BY c.is_main_course DESC, c.id ASC ) c_data ) as courses FROM facilities f WHERE f.slug = $1 """, slug) if not row: raise HTTPException(status_code=404) return format_row(row)