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:
1 parent
fdbb31065f
commit
56c4f38ef0
10 files changed
+210
-22
No files matched your search
@@ -232,6 +232,16 @@ CREATE TABLE IF NOT EXISTS travel_visits (
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
-- Wohnort pro Konto: Start und Ziel jeder Reise für die Kilometer-Statistik
|
||||
CREATE TABLE IF NOT EXISTS travel_home (
|
||||
user_id INTEGER PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
||||
geoname_id INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
country TEXT NOT NULL,
|
||||
lat REAL NOT NULL,
|
||||
lon REAL NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS travel_visit_photos (
|
||||
visit_id INTEGER NOT NULL REFERENCES travel_visits(id) ON DELETE CASCADE,
|
||||
file TEXT NOT NULL, -- Datei in data/uploads (ohne Metadaten gespeichert)
|
||||
|
||||
@@ -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}")
|
||||
|
||||
Reference in new issue
Block a user