Reisen: Wohnort und nachvollziehbare Kilometer-Rechnung

- Wohnort pro Konto (Tabelle travel_home), im Tab "Statistik" über die
  Städtesuche festlegen, auf der Karte als ⌂
- Kilometer (route.js): jede Reise mit Hin- und Heimweg ab Wohnort;
  Reisen mit höchstens einem Tag Abstand als Rundreise; Besuche während
  eines längeren Aufenthalts als Ausflug hin und zurück; ohne Wohnort
  werden Reisen direkt verbunden
- "Wie gerechnet?" listet alle Teilstrecken; Reisetage zählen jeden Tag
  nur einmal (Ausflüge im Aufenthalt nicht doppelt)
- Wohnort-Suche mit eigenen IDs (zwei Suchfelder auf der Seite)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
guyg1474andClaude Opus 5.5 committed 2026-10-15 20:31:52 +02:00
1 parent fdbb31065f
commit 56c4f38ef0
10 files changed
+210 -22

No files matched your search

+35
View File
@@ -90,9 +90,11 @@ def _visits(conn, user_id: int) -> list:
def _state(conn, user_id: int) -> dict:
cities = conn.execute("SELECT * FROM travel_cities WHERE user_id = ? ORDER BY name", (user_id,)).fetchall()
countries = conn.execute("SELECT code FROM travel_countries WHERE user_id = ? ORDER BY code", (user_id,)).fetchall()
home = conn.execute("SELECT * FROM travel_home WHERE user_id = ?", (user_id,)).fetchone()
return {
"cities": [_city(r) for r in cities],
"countries": [r["code"] for r in countries],
"home": {k: home[k] for k in ("name", "country", "lat", "lon")} | {"geonameId": home["geoname_id"]} if home else None,
"visits": _visits(conn, user_id),
"others": _others(conn, user_id),
}
@@ -178,6 +180,39 @@ def update_city(city_id: int, data: dict = Body(...), user: dict = Depends(curre
return _state(conn, user["id"])
# ---------- Wohnort ----------
@router.put("/api/reisen/wohnort")
def set_home(data: dict = Body(...), user: dict = Depends(current_user)):
"""Wohnort festlegen (Ergebnis der Städtesuche); nur für die eigene Kilometer-Statistik."""
geoname_id = data.get("geonameId")
if isinstance(geoname_id, bool) or not isinstance(geoname_id, int) or geoname_id <= 0:
raise ValidationError("Ungültige Stadt.")
country = data.get("country")
if not isinstance(country, str) or not re.fullmatch(r"[A-Z]{2}", country):
raise ValidationError("Ungültiges Land.")
values = (
user["id"], geoname_id, clean_text(data.get("name"), "Name", 100), country,
_number(data.get("lat"), "Breitengrad", -90, 90), _number(data.get("lon"), "Längengrad", -180, 180),
)
with transaction() as conn:
conn.execute(
"""INSERT INTO travel_home (user_id, geoname_id, name, country, lat, lon) VALUES (?, ?, ?, ?, ?, ?)
ON CONFLICT (user_id) DO UPDATE SET geoname_id = excluded.geoname_id, name = excluded.name,
country = excluded.country, lat = excluded.lat, lon = excluded.lon""",
values,
)
return _state(conn, user["id"])
@router.delete("/api/reisen/wohnort")
def delete_home(user: dict = Depends(current_user)):
with transaction() as conn:
conn.execute("DELETE FROM travel_home WHERE user_id = ?", (user["id"],))
return _state(conn, user["id"])
# ---------- Besuche: Zeitraum, Begleitung, Notizen, Fotos ----------
DATE = re.compile(r"\d{4}-\d{2}-\d{2}")