neue Archivfunktion und Optimierung an Artikelbearbeitung
This commit is contained in:
114
README.md
114
README.md
@@ -551,6 +551,7 @@ Einzeln:
|
||||
bash tools/check-env.sh .env # doppelte oder fehlerhafte .env-Einträge
|
||||
python3 tools/check-routes.py # Endpunkte ohne Berechtigungsprüfung
|
||||
python3 tools/check-schema.py # db/schema.sql gegen die Modelle
|
||||
python3 tools/check-editable.py # Felder eines Eintrags überall verdrahtet?
|
||||
python3 tools/check-nginx.py web # Kopfzeilen, doppelte Direktiven
|
||||
node tools/check-js.mjs # undefinierte Bezeichner in den JS-Modulen
|
||||
node tools/test-barcode.mjs # Strichcode-Decoder
|
||||
@@ -575,6 +576,16 @@ der weder eine Prüfung noch einen Eintrag in der Ausnahmeliste hat. FastAPI
|
||||
mahnt fehlende Absicherung nicht an – beim Hinzufügen einer Route ist sie schnell
|
||||
vergessen.
|
||||
|
||||
### `check-editable.py`
|
||||
|
||||
Prüft, dass jedes änderbare Feld eines Listeneintrags auch tatsächlich überall
|
||||
eingetragen ist: Modell, `ItemUpdateIn`, `ItemOut`, `items.py`, `sync.py` und
|
||||
die Oberfläche.
|
||||
|
||||
Ein Feld hinzuzufügen bedeutet sechs Stellen. Fehlt eine, merkt es niemand: Die
|
||||
Anwendung startet, die Oberfläche zeigt ein Eingabefeld, der Server verwirft den
|
||||
Wert stillschweigend. Genau so ist der Artikelname zunächst untergegangen.
|
||||
|
||||
### `check-schema.py`
|
||||
|
||||
Vergleicht `db/schema.sql` mit den SQLAlchemy-Modellen: fehlende oder
|
||||
@@ -1119,12 +1130,14 @@ das geht bewusst nur direkt in der Datenbank.
|
||||
|
||||
### Automatische Bereinigung
|
||||
|
||||
Zwei Fristen, in der Verwaltung einstellbar:
|
||||
Vier Fristen, in der Verwaltung einstellbar:
|
||||
|
||||
| Einstellung | Voreinstellung | Wirkung |
|
||||
|---|---|---|
|
||||
| Deaktivieren nach … Monaten ohne Anmeldung | 12 | Konto wird gesperrt, Person bekommt eine Nachricht |
|
||||
| Löschen nach … Monaten Deaktivierung | 12 | Konto wird endgültig entfernt |
|
||||
| Konto deaktivieren nach … Monaten ohne Anmeldung | 12 | Konto wird gesperrt, Person bekommt eine Nachricht |
|
||||
| Konto löschen nach … Monaten Deaktivierung | 12 | Konto wird endgültig entfernt |
|
||||
| Liste archivieren nach … Monaten ohne Öffnen | 12 | **Je Person** – die Liste verschwindet nur aus deren Übersicht |
|
||||
| Liste löschen nach … Monaten im Archiv | 12 | Nur nach dem Archivdatum des **Eigentümers** |
|
||||
|
||||
**0 bedeutet abgeschaltet, nicht „sofort".** Ein Tippfehler soll nicht dazu
|
||||
führen, dass beim nächsten Durchlauf alle Konten verschwinden.
|
||||
@@ -1137,6 +1150,101 @@ Grundlage ist `user.last_seen_at`. Der Wert wird bei der Anmeldung gesetzt und
|
||||
danach höchstens stündlich nachgeführt, damit auch jemand mitzählt, der sich
|
||||
monatelang nicht neu anmeldet, weil die Sitzung hält.
|
||||
|
||||
## Archiv
|
||||
|
||||
Jede Liste kann archiviert werden – **je Person getrennt.** Wer eine gemeinsame
|
||||
Liste nicht mehr braucht, nimmt sie aus seiner Übersicht, ohne sie den anderen
|
||||
wegzunehmen.
|
||||
|
||||
In der Listenübersicht erscheint unterhalb der aktiven Listen ein aufklappbarer
|
||||
Abschnitt „Archiv". Archivieren und Zurückholen stehen im „⋯"-Menü jeder Zeile
|
||||
und stehen allen Mitgliedern offen, nicht nur dem Eigentümer.
|
||||
|
||||
| Methode | Pfad |
|
||||
|---|---|
|
||||
| GET | `/api/lists?archived=false\|true` – ohne Parameter alle |
|
||||
| POST | `/api/lists/{id}/archive`, `/unarchive` |
|
||||
|
||||
### Automatisch archivieren
|
||||
|
||||
Wer eine Liste zwölf Monate nicht geöffnet hat, findet sie danach im Archiv.
|
||||
Grundlage ist `list_member.last_opened_at`, gesetzt bei jedem Zugriff und
|
||||
höchstens stündlich nachgeführt.
|
||||
|
||||
Das wirkt sich **individuell** aus: Öffnet ein Mitglied die Liste regelmäßig
|
||||
und ein anderes nie, bleibt sie beim einen aktiv und wandert beim anderen ins
|
||||
Archiv.
|
||||
|
||||
### Automatisch löschen
|
||||
|
||||
Maßgeblich ist **allein das Archivdatum des Eigentümers.** Dass ein
|
||||
eingeladenes Mitglied die Liste weggeräumt hat, sagt nichts darüber, ob sie
|
||||
noch gebraucht wird – sonst könnte jemand, der einmal eingeladen wurde und
|
||||
nie wieder hineinschaut, eine Löschung auslösen, die den Eigentümer trifft.
|
||||
|
||||
Zwei Sicherungen gegen Datenverlust:
|
||||
|
||||
**Vorwarnungen per E-Mail** an den Eigentümer, 7 Tage und 1 Tag vor der
|
||||
Löschung. Jede Stufe genau einmal – eine tägliche Erinnerung wäre Belästigung
|
||||
statt Warnung. Ein Klick auf „Aus dem Archiv holen" setzt die Frist zurück und
|
||||
löscht auch die Warnvermerke, damit beim nächsten Mal wieder gewarnt wird.
|
||||
|
||||
**Wer die Liste zwischenzeitlich geöffnet hat, verliert sie nicht** – auch wenn
|
||||
das Archivdatum alt ist. Ohne diese Prüfung könnte eine manuell archivierte,
|
||||
aber weiterhin benutzte Liste verschwinden.
|
||||
|
||||
Gelöscht wird per Soft Delete: Offline gebliebene Geräte erfahren noch davon,
|
||||
endgültig entfernt der Aufräumlauf nach `CLEANUP_DELETED_DAYS`.
|
||||
|
||||
## Einträge bearbeiten
|
||||
|
||||
Im „⋯"-Menü eines Eintrags lässt sich alles ändern: **Artikel**, Anzahl,
|
||||
Gebinde, Einheit, Eigenschaft, Notiz, Markt, Warengruppe, Preis und Status.
|
||||
|
||||
### Artikel wechseln oder umbenennen
|
||||
|
||||
Der Name gehört nicht dem Eintrag, sondern dem Artikel dahinter – und der kann
|
||||
von mehreren Einträgen benutzt werden, trägt einen Strichcode, Vorgaben für
|
||||
Markt und Warengruppe und hängt an der Preishistorie. Ein Namenswechsel am
|
||||
Eintrag ist deshalb mehrdeutig:
|
||||
|
||||
```
|
||||
"Mlich" → "Milch" ein Tippfehler soll verschwinden
|
||||
"Milch" → "Butter" dieser Eintrag soll etwas anderes sein
|
||||
```
|
||||
|
||||
Die Regel: **Benutzt außer diesem Eintrag niemand den Artikel, wird er
|
||||
umbenannt** – der Tippfehler verschwindet dann restlos. Sonst hängt der Eintrag
|
||||
auf einen anderen Artikel um, und die übrigen Einträge bleiben unberührt.
|
||||
|
||||
Bleibt der bisherige Artikel dabei ohne Einträge zurück und hängt nichts
|
||||
Gepflegtes daran (kein Strichcode, keine Eigenschaften, keine Vorgaben, keine
|
||||
beobachteten Preise), verschwindet er mit. Wo etwas dranhängt, bleibt er
|
||||
stehen – dort stört er nicht und lässt sich von Hand löschen.
|
||||
|
||||
Wer einen Artikel ausdrücklich **überall** umbenennen will, tut das unter
|
||||
„Artikel"; dort ist der Name ein Feld wie jedes andere.
|
||||
|
||||
## Vorschläge beim Eintippen
|
||||
|
||||
Ab drei Zeichen im Feld „Artikel hinzufügen" erscheint eine Liste dessen, was
|
||||
auf dieser Liste schon eingetragen wurde – von **allen** Mitgliedern, aus den
|
||||
letzten 24 Monaten.
|
||||
|
||||
Quelle sind die Listeneinträge, **auch die bereits gelöschten**: Gerade die
|
||||
abgehakten und aufgeräumten sind die interessanten. Was jemand vor drei Jahren
|
||||
einmal gekauft hat, hilft dagegen nicht mehr und würde die Liste nur
|
||||
verlängern.
|
||||
|
||||
Ein Antippen füllt Name, Anzahl, Gebinde, Eigenschaft sowie Markt und
|
||||
Warengruppe mit den zuletzt verwendeten Werten – **trägt den Artikel aber noch
|
||||
nicht ein.** Der Fokus springt ins Gebinde-Feld, damit noch Änderungen möglich
|
||||
sind. Erst „Hinzufügen" oder Enter übernimmt.
|
||||
|
||||
Sortiert nach Häufigkeit, dann nach Aktualität; höchstens acht Vorschläge.
|
||||
|
||||
`GET /api/lists/{id}/articles/suggest?q=…`
|
||||
|
||||
## Datenbankschema
|
||||
|
||||
`db/schema.sql` enthält das vollständige Schema (Revision `0011`).
|
||||
|
||||
Reference in New Issue
Block a user