Nye-TeeOff/backend/main.py

95 lines
No EOL
3.2 KiB
Python

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)