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): app.state.pool = await asyncpg.create_pool(DB_URL, min_size=5, max_size=20) yield await app.state.pool.close() app = FastAPI(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) for key in ['status_updated_at', 'created_at']: if isinstance(d.get(key), (date, datetime)): d[key] = d[key].isoformat() # JSONB vask - Mapper direkte mot kolonnene i struktur_dump.txt json_fields = ['amenities', 'greenfee', 'membership', 'vtg', 'faqs', 'shotzoom', 'translations', 'course_statuses', 'courses', 'gallery', 'nsg_data', 'golfamore_data'] for field in json_fields: if field in d: if isinstance(d[field], str): try: d[field] = json.loads(d[field]) except: pass if d[field] is None: d[field] = [] if field in ['courses', 'faqs', 'gallery'] else {} 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 NOT IN ('finnes_ingen_bane_to', 'nedlagt') 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', 'nedlagt', '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)