"""BAN YARO — Service-Angebote (Sitting & Walks Matching)""" import math from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel from typing import Optional from database import db from auth import get_current_user router = APIRouter() ALLOWED_TYPES = {'sitting', 'walks'} def _haversine(lat1, lon1, lat2, lon2): R = 6371.0 dlat = math.radians(lat2 - lat1) dlon = math.radians(lon2 - lon1) a = (math.sin(dlat / 2) ** 2 + math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.sin(dlon / 2) ** 2) return R * 2 * math.asin(math.sqrt(a)) # ------------------------------------------------------------------ # Schemas # ------------------------------------------------------------------ class ServiceCreate(BaseModel): type: str beschreibung: Optional[str] = None preis_pro_tag: Optional[float] = None lat: Optional[float] = None lon: Optional[float] = None radius_km: int = 10 # ------------------------------------------------------------------ # GET /api/services — Angebote in der Nähe # ------------------------------------------------------------------ @router.get("") async def list_services( type: str, lat: Optional[float] = None, lon: Optional[float] = None, radius: float = 20, # km ): if type not in ALLOWED_TYPES: raise HTTPException(400, f"type muss 'sitting' oder 'walks' sein.") with db() as conn: rows = conn.execute(""" SELECT so.*, u.name AS anbieter_name FROM service_offers so JOIN users u ON u.id = so.user_id WHERE so.type = ? AND so.aktiv = 1 LIMIT 200 """, (type,)).fetchall() result = [] for r in rows: d = dict(r) if lat is not None and lon is not None and d['lat'] and d['lon']: dist = _haversine(lat, lon, d['lat'], d['lon']) if dist > radius: continue d['distanz_km'] = round(dist, 1) else: d['distanz_km'] = None result.append(d) if lat is not None: result.sort(key=lambda x: x.get('distanz_km') or 9999) return result[:50] # ------------------------------------------------------------------ # GET /api/services/me — eigene Angebote # ------------------------------------------------------------------ @router.get("/me") async def my_services(user=Depends(get_current_user)): with db() as conn: rows = conn.execute( "SELECT * FROM service_offers WHERE user_id = ? ORDER BY type", (user['id'],) ).fetchall() return [dict(r) for r in rows] # ------------------------------------------------------------------ # POST /api/services — Angebot erstellen oder aktualisieren (Upsert) # ------------------------------------------------------------------ @router.post("", status_code=201) async def upsert_service(data: ServiceCreate, user=Depends(get_current_user)): if data.type not in ALLOWED_TYPES: raise HTTPException(400, "type muss 'sitting' oder 'walks' sein.") with db() as conn: existing = conn.execute( "SELECT id FROM service_offers WHERE user_id = ? AND type = ?", (user['id'], data.type) ).fetchone() if existing: conn.execute(""" UPDATE service_offers SET beschreibung = ?, preis_pro_tag = ?, lat = ?, lon = ?, radius_km = ?, aktiv = 1 WHERE user_id = ? AND type = ? """, (data.beschreibung, data.preis_pro_tag, data.lat, data.lon, data.radius_km, user['id'], data.type)) row = conn.execute( "SELECT * FROM service_offers WHERE user_id = ? AND type = ?", (user['id'], data.type) ).fetchone() else: cur = conn.execute(""" INSERT INTO service_offers (user_id, type, beschreibung, preis_pro_tag, lat, lon, radius_km) VALUES (?, ?, ?, ?, ?, ?, ?) """, (user['id'], data.type, data.beschreibung, data.preis_pro_tag, data.lat, data.lon, data.radius_km)) row = conn.execute( "SELECT * FROM service_offers WHERE id = ?", (cur.lastrowid,) ).fetchone() return dict(row) # ------------------------------------------------------------------ # DELETE /api/services/{id} — Angebot deaktivieren # ------------------------------------------------------------------ @router.delete("/{offer_id}") async def deactivate_service(offer_id: int, user=Depends(get_current_user)): with db() as conn: offer = conn.execute( "SELECT * FROM service_offers WHERE id = ?", (offer_id,) ).fetchone() if not offer: raise HTTPException(404, "Angebot nicht gefunden.") if offer['user_id'] != user['id']: raise HTTPException(403, "Kein Zugriff.") conn.execute( "UPDATE service_offers SET aktiv = 0 WHERE id = ?", (offer_id,) ) return {"ok": True}