tschunkorder/backend/main.py
2025-07-09 22:18:21 +02:00

122 lines
No EOL
3.8 KiB
Python

from fastapi import FastAPI, HTTPException, WebSocket, WebSocketDisconnect
from typing import List
from models import CreateOrderRequest, Order, DrinkType, MateType
from database import db
from websocket_manager import websocket_manager
app = FastAPI(
title="Tschunk Order API",
description="Eine RESTful API für Tschunk-Bestellungen mit WebSocket-Unterstützung",
version="1.0.0"
)
@app.get("/")
async def root():
"""Root endpoint with API information."""
return {
"message": "Willkommen zur Tschunk Order API!",
"version": "1.0.0",
"endpoints": {
"POST /orders": "Neue Bestellung erstellen",
"GET /orders": "Alle Bestellungen abrufen",
"DELETE /orders/{order_id}": "Bestellung löschen",
"WS /ws": "WebSocket für Echtzeit-Updates"
},
"available_drinks": [drink.value for drink in DrinkType],
"available_mate_types": [mate.value for mate in MateType]
}
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
"""
WebSocket-Endpunkt für Echtzeit-Updates der Bestellungen.
Clients erhalten automatisch Updates bei:
- Neuen Bestellungen
- Gelöschten Bestellungen
Nachrichten-Formate:
- order_created: {"type": "order_created", "order": {...}}
- order_deleted: {"type": "order_deleted", "order_id": "..."}
- all_orders: {"type": "all_orders", "orders": [...]}
"""
await websocket_manager.connect(websocket)
try:
# Sende alle aktuellen Bestellungen beim Verbinden
all_orders = [order.model_dump() for order in db.get_all_orders()]
await websocket_manager.broadcast_all_orders(all_orders)
# Halte die Verbindung aufrecht und warte auf Nachrichten
while True:
# Warte auf Nachrichten vom Client (kann für Pings/Pongs verwendet werden)
data = await websocket.receive_text()
# Optional: Echo für Pings
if data == "ping":
await websocket.send_text("pong")
except WebSocketDisconnect:
websocket_manager.disconnect(websocket)
except Exception as e:
print(f"WebSocket-Fehler: {e}")
websocket_manager.disconnect(websocket)
@app.post("/orders", response_model=Order, status_code=201)
async def create_order(order_request: CreateOrderRequest):
"""
Erstellt eine neue Bestellung.
- **drinks**: Liste der Getränke mit Typ und Mate-Sorte
Alle verbundenen WebSocket-Clients erhalten automatisch ein Update.
"""
if not order_request.drinks:
raise HTTPException(status_code=400, detail="Mindestens ein Getränk muss bestellt werden")
order = await db.create_order(order_request.drinks)
return order
@app.get("/orders", response_model=List[Order])
async def get_all_orders():
"""
Gibt alle Bestellungen zurück.
"""
orders = db.get_all_orders()
return orders
@app.delete("/orders/{order_id}")
async def delete_order(order_id: str):
"""
Löscht eine spezifische Bestellung.
- **order_id**: ID der zu löschenden Bestellung
Alle verbundenen WebSocket-Clients erhalten automatisch ein Update.
"""
success = await db.delete_order(order_id)
if not success:
raise HTTPException(status_code=404, detail="Bestellung nicht gefunden")
return {"message": f"Bestellung {order_id} wurde erfolgreich gelöscht"}
@app.get("/drinks")
async def get_available_drinks():
"""
Gibt alle verfügbaren Getränketypen zurück.
"""
return {
"drink_types": [drink.value for drink in DrinkType],
"mate_types": [mate.value for mate in MateType]
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)