Backend: gemeinsame Helfer in common.py
- Eine ValidationError-Klasse statt zwei (links.py, projects.py), ein Fehler-Handler in main.py - clean_text() ersetzt vier fast gleiche Text-Prüfungen (Kanban, Haushalt, Reisen, Artikel); Fehlermeldungen nennen jetzt überall die Höchstlänge - Zeitstempel (now_iso, iso_ago, iso_after) und Kontenliste (user_list) an einer Stelle; ungenutzte Importe entfernt - Tests für die Helfer und für einheitliche 400-Fehler aus allen Bereichen Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d28e6b2e4b
commit
4aba48ce51
14 files changed
+117
-86
No files matched your search
+5
-16
@@ -7,13 +7,12 @@ Wer eine Liste anlegt, legt fest, ob alle Konten sie sehen oder nur ausgewählte
|
||||
Vorschläge angeboten – "milch" wird dabei automatisch zum bereits bekannten "Milch".
|
||||
"""
|
||||
import math
|
||||
import re
|
||||
|
||||
from fastapi import APIRouter, Body, Depends, HTTPException
|
||||
|
||||
from .auth import current_user
|
||||
from .db import now_iso, transaction
|
||||
from .links import ValidationError
|
||||
from .common import ValidationError, clean_text, now_iso, user_list
|
||||
from .db import transaction
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -67,12 +66,7 @@ def _quantity(value, unit: str = "stk"):
|
||||
|
||||
|
||||
def _clean_name(value) -> str:
|
||||
name = re.sub(r"\s+", " ", value).strip() if isinstance(value, str) else ""
|
||||
if not name:
|
||||
raise ValidationError("Produktname fehlt.")
|
||||
if len(name) > MAX_NAME:
|
||||
raise ValidationError(f"Produktname ist zu lang (max. {MAX_NAME} Zeichen).")
|
||||
return name
|
||||
return clean_text(value, "Produktname", MAX_NAME)
|
||||
|
||||
|
||||
def _key(name: str) -> str:
|
||||
@@ -168,11 +162,7 @@ def _shopping_list(conn, row, user: dict) -> dict:
|
||||
|
||||
def _list_fields(conn, data: dict, user: dict, owner_id) -> tuple:
|
||||
"""Name, "für alle" und Mitglieder prüfen. Der Ersteller sieht seine Liste immer und steht nicht bei den Mitgliedern."""
|
||||
name = re.sub(r"\s+", " ", data.get("name")).strip() if isinstance(data.get("name"), str) else ""
|
||||
if not name:
|
||||
raise ValidationError("Name der Liste fehlt.")
|
||||
if len(name) > MAX_LIST_NAME:
|
||||
raise ValidationError(f"Name ist zu lang (max. {MAX_LIST_NAME} Zeichen).")
|
||||
name = clean_text(data.get("name"), "Name der Liste", MAX_LIST_NAME)
|
||||
everyone = data.get("everyone", True)
|
||||
if not isinstance(everyone, bool):
|
||||
raise ValidationError("Ungültige Sichtbarkeit.")
|
||||
@@ -211,11 +201,10 @@ def _state(conn, user: dict) -> dict:
|
||||
).fetchall()
|
||||
# Häufig genutzte Produkte zuerst vorschlagen
|
||||
products = conn.execute("SELECT name, uses FROM products").fetchall()
|
||||
users = conn.execute("SELECT id, display_name FROM users ORDER BY display_name COLLATE NOCASE").fetchall()
|
||||
return {
|
||||
"items": [_item(r) for r in sorted(items, key=lambda r: _sort_key(r["name"]))],
|
||||
"lists": [_shopping_list(conn, r, user) for r in lists],
|
||||
"users": [{"id": u["id"], "name": u["display_name"]} for u in users],
|
||||
"users": user_list(conn),
|
||||
"products": [r["name"] for r in sorted(products, key=lambda r: (-r["uses"], _sort_key(r["name"])))],
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user