From d04b6b74ad8ecda4a0e69c15d9f4eb702ca5237b Mon Sep 17 00:00:00 2001 From: Guido Date: Wed, 21 Oct 2026 21:07:06 +0200 Subject: [PATCH] docs: Uebergabe, README und Fahrplan halten Stufe 3 fest Neu drin: die vier Regeln, die man nicht sieht, aber merkt, wenn sie fehlen (Teilaenderung schickt nur Gesetztes, leere Tag-Liste bedeutet etwas, kein Kategorie beim Uebertrag, planned_cents bleibt bei "berechnet" unberuehrt), und warum die Waehrung eines bestehenden Kontos nicht aenderbar ist. Dazu der Befehl, mit dem man fehlende Uebersetzungen findet - ein unbekannter Schluessel uebersetzt anstandslos und zeigt dem Nutzer den Schluessel. Festgehalten, was aus Stufe 3 bewusst nicht mitkam: Vertragslogo und Kontoreihenfolge. Und wo der 409-Fall wartet: an POST /transactions/{id}/transfer, also in Stufe 4. Co-Authored-By: Claude Opus 5 --- docs/ROADMAP.md | 11 ++--- ios/README.md | 6 +-- ios/UEBERGABE.md | 107 +++++++++++++++++++++++++++++++++++++---------- 3 files changed, 93 insertions(+), 31 deletions(-) diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 0034886..6ef2656 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -52,10 +52,11 @@ zweispaltig, offline der letzte Stand mit Datum. Stufe 1 ✅: Gerüst, Netzwerkschicht, Anmeldung samt zweitem Faktor und Pflicht-Passwortwechsel, Kontenliste. Stufe 2 ✅: Übersicht, Budget-Monat, -Buchungsliste mit Suche, Vertragsliste. Übersetzt fehlerfrei, 44 Tests grün, -läuft im Simulator; das Xcode-Projekt entsteht aus `ios/project.yml`, die -Modelle werden gegen echte Serverantworten geprüft. -Stufen 3–7 (Schreiben, Arbeitsliste, Nebenräume, Erweiterungen, voller -CSV-Import) stehen aus. +Buchungsliste mit Suche, Vertragsliste. Stufe 3 ✅: Buchungen, Budget-Zeilen, +Verträge und Konten anlegen, ändern und löschen. Übersetzt fehlerfrei, +49 Tests grün, läuft im Simulator; das Xcode-Projekt entsteht aus +`ios/project.yml`, die Modelle werden gegen echte Serverantworten geprüft. +Stufen 4–7 (Arbeitsliste, Nebenräume, Erweiterungen, voller CSV-Import) +stehen aus. **Stand, Entscheidungen und offene Punkte: `ios/UEBERGABE.md`.** diff --git a/ios/README.md b/ios/README.md index 1de9fd7..c020a03 100644 --- a/ios/README.md +++ b/ios/README.md @@ -41,13 +41,13 @@ Vollzugang. Wer eine Ausnahme braucht, trägt sie bewusst in `project.yml` ein. | `App/` | Einstiegspunkt, Navigation, globaler Zustand | | `Netzwerk/` | Client, Endpunkte, Fehler, Offline-Ablage | | `Modelle/` | Codable-Typen, eins zu eins zu den Backend-Schemas | -| `Bausteine/` | Wiederverwendetes: Geld, Farben, Symbole, Zustandsansichten | +| `Bausteine/` | Wiederverwendetes: Geld, Farben, Symbole, Zustandsansichten, Formularfelder | | `Anmeldung/` | Server-Adresse, Anmeldung, zweiter Faktor, Passwortwechsel | | `Dashboard/` | Die Übersicht: vier feste Karten | | `Budget/` | Soll gegen Ist, Monat für Monat | -| `Buchungen/` | Buchungsliste mit Suche und Filtern | +| `Buchungen/` | Buchungsliste mit Suche, Formular zum Anlegen und Ändern | | `Abos/` | Verträge und Abos | -| `Konten/` | Kontenliste | +| `Konten/` | Kontenliste und Konto-Formular | | `Texte/` | Übersetzungen, Deutsch und Englisch zeilengleich | | `Tests/` | Logiktests ohne Netz, plus die Modellprüfung gegen `Fixtures/antworten.json` | diff --git a/ios/UEBERGABE.md b/ios/UEBERGABE.md index b04c945..978c0d4 100644 --- a/ios/UEBERGABE.md +++ b/ios/UEBERGABE.md @@ -6,7 +6,7 @@ haben: was entschieden ist, was fertig ist, was als Nächstes dran ist, und was ich über das Backend herausgefunden habe. Lies sie ganz, bevor du anfängst — die Abschnitte „Was das Backend vorgibt" und „Fallen" ersparen dir Tage. -Stand: 21.10.2026, Commit `ffe1870`. Alles committet und gepusht. +Stand: 21.10.2026, Commit `82db09e`. Alles committet und gepusht. --- @@ -173,8 +173,8 @@ umgestellt, weil sie so funktioniert. Die App soll die Filter benutzen. ## 4. Backend-Ergänzungen -Vier geplant. **A, B und C sind fertig**, D steht aus. Jede einzeln dem Nutzer -vorlegen, bevor du sie schreibst. +Vier geplant, **alle vier sind fertig**. Falls du eine fünfte brauchst: einzeln +dem Nutzer vorlegen, bevor du sie schreibst. ### A — App-Token ✅ (Commit `8a7545b`) @@ -225,17 +225,24 @@ zeigt eine berechnete Zeile als feste **und schreibt sie beim nächsten Speichern auch als feste zurück**. Die Weboberfläche traf es nicht, weil sie die Betriebsart aus der Monatsansicht nimmt. -### D — Zwei Kopier-Lücken im Budget (offen) +### D — Zwei Kopier-Lücken im Budget ✅ -`copy_template_to_month` und `template_from_month` in -`backend/app/services/budget.py` übernehmen nur `planned_cents`. Ein -„berechneter" Eintrag fällt beim Kopieren still auf „fest" zurück. Das ist ein -**bestehender Fehler**, kein App-Thema — aber die App macht ihn sichtbar, weil -sie beide Richtungen anbietet. Nötig für Stufe 3. +`copy_template_to_month` und `copy_month_to_template` in +`backend/app/services/budget.py` übernahmen nur `planned_cents`. Ein +„berechneter" Eintrag fiel beim Kopieren still auf „fest" zurück — mit der +Zahl, die zufällig zuletzt in `planned_cents` stand. + +`ensure_customized` nebenan machte es längst richtig; die zwei Kopierer ziehen +jetzt nach. Dabei kam eine Frage auf, die vorher niemand stellen musste: Eine +**berechnete** Zeile gehört auch mit `planned_cents == 0` in die Vorlage, ihre +Zahl steht ja in den Verträgen. Eine **feste** Null bleibt draussen, sonst +füllte sich die Vorlage mit Nullzeilen für jede je berührte Kategorie. + +Drei Tests in `test_budget.py` halten beide Richtungen und die Null fest. --- -## 5. Was fertig ist — Stufen 1 und 2 ✅ +## 5. Was fertig ist — Stufen 1 bis 3 ✅ ### Stufe 1 (Commit `6b86a6b`) @@ -335,20 +342,72 @@ committen: cd backend && .venv/bin/python -m scripts.erzeuge_ios_fixture ``` -Wer ein Modell für Stufe 3 ergänzt, nimmt seinen Endpunkt in `PFADE` auf und -schreibt eine Zeile im Test dazu. Das ist die einzige Prüfung, die einen -vertippten Feldnamen fängt — der übersetzt anstandslos. +Wer ein Modell ergänzt, nimmt seinen Endpunkt in `PFADE` auf und schreibt eine +Zeile im Test dazu. Das ist die einzige Prüfung, die einen vertippten +Feldnamen fängt — der übersetzt anstandslos. + +### Stufe 3 — Schreiben ✅ (Commit `82db09e`) + +Buchungen, Budget-Zeilen, Verträge und Konten lassen sich anlegen, ändern und +löschen. + +| Datei | Inhalt | +|---|---| +| `Modelle/Eingaben.swift` | Was zum Server hinausgeht | +| `Bausteine/Formular.swift` | Speichervorgang, Betragsfeld, Auswahlfelder | +| `Buchungen/BuchungFormular.swift` | Anlegen **und** Ändern in einer Maske | +| `Budget/BudgetZeileBearbeiten.swift` | Monat oder Vorlage, dieselbe Maske | +| `Abos/AboFormular.swift`, `Konten/KontoFormular.swift` | ebenso | + +**Ein Formular je Sache, nicht zwei.** Anlegen und Ändern teilen sich die +Maske; was sich unterscheidet, steht in einem `Zweck`-Typ. Zwei Masken +nebeneinander wären genau die Stelle, an der sie auseinanderlaufen. + +#### Vier Regeln, die man nicht sieht, aber merkt, wenn sie fehlen + +1. **Eine Teiländerung schickt nur, was gesetzt ist.** Ginge ein nicht + angefasstes Feld als `null` hinaus, löschte jedes Speichern den Empfänger, + die Notiz und die Kategorie gleich mit. Swift macht das von selbst + (`encodeIfPresent` für Optionals) — der Test dazu bleibt trotzdem stehen, + die Eigenschaft ist zu wichtig für eine ungeprüfte Spracheigenheit. +2. **Eine leere Tag-Liste geht sehr wohl mit.** Sie heisst „alle abnehmen" und + darf nicht mit „nicht angefasst" zusammenfallen. +3. **Ein Übertrag bekommt keine Kategorie.** Das Geld wechselt nur die Tasche. +4. **Bei „berechnet" bleibt `planned_cents` unberührt.** Das Backend liest es + dann nicht, und es zu überschreiben verlöre den Wert, auf den ein + Zurückschalten auf „fest" zurückfallen soll. + +Die **Währung eines bestehenden Kontos** lässt sich nicht ändern — jeder +gespeicherte Betrag würde danach etwas anderes bedeuten. Das Backend erlaubt +es; die App nicht. + +#### Fehlende Texte findet dieser Befehl + +`String(localized:)` mit unbekanntem Schlüssel übersetzt anstandslos und zeigt +dem Nutzer den Schlüssel. Vor dem Committen: + +``` +cd ios && comm -23 \ + <(grep -rhoE 'localized: "[a-zA-Z0-9._]+"' --include="*.swift" . | sed 's/localized: "//; s/"//' | sort -u) \ + <(grep -oE '^"[a-zA-Z0-9._]+"' Texte/de.lproj/Localizable.strings | tr -d '"' | sort -u) +``` + +Gibt er nichts aus, ist nichts offen. (Ein Schlüssel, der nur in einem +`? :` steckt, taucht fälschlich als „fehlend" nicht auf — das ist die eine +Lücke des Befehls.) Dass beide Sprachfassungen dieselben Schlüssel tragen, +prüft ein `diff` der beiden `grep`-Ausgaben. --- ## 6. Was als Nächstes dran ist -**Stufe 3 ist dran.** Davor liegt nur noch Backend-Ergänzung **D** (unten), -die zwei Kopier-Lücken im Budget. +**Stufe 4 ist dran.** Alle vier Backend-Ergänzungen sind drin; von hier an +reicht die API, wie sie ist. -**Stufe 3 — Schreiben.** Buchungen anlegen und ändern, Budget bearbeiten -(Monat und Vorlage, beide Betriebsarten `fest`/`berechnet`), Abos verwalten -samt Logo, Konten bearbeiten. Dazu Backend-Ergänzung **D**. +Was aus Stufe 3 bewusst nicht mitkam: das **Logo** eines Vertrags (Upload und +Zuschnitt, `POST /subscriptions/{id}/logo`) und die **Reihenfolge** der Konten +(`PUT /accounts/order`). Beides ist am Rechner bequemer und hielt niemanden +auf. **Stufe 4 — Arbeitsliste.** Eingang mit Buchen, Verwerfen, Kategorie zuordnen, Übertragsvorschlägen und Dubletten. Fachlich der Teil, der am besten aufs @@ -372,12 +431,14 @@ Vorlagen, Verlauf mit Rücknahme. ### Zum Umfang, ehrlich Die Weboberfläche hat rund 8900 Zeilen JSX. Nativ wird das nicht weniger. -Stufe 2 hat rund 1800 Zeilen gebraucht; Stufen 3 bis 6 zusammen sind grob -zwei bis drei Wochen, Stufe 7 nochmal zwei bis drei. +Stufe 2 hat rund 1800 Zeilen gebraucht, Stufe 3 rund 1200; Stufen 4 bis 6 +zusammen sind grob ein bis zwei Wochen, Stufe 7 nochmal zwei bis drei. -Stufe 3 wird die aufwendigste der verbliebenen: Schreiben heisst Formulare, -Fehlerbehandlung je Feld und der 409-Fall („nachfragen", oft mit -`trotzdem=true` wiederholbar). Lesen war dagegen geradeaus. +Der **409-Fall** („nachfragen", mit `trotzdem=true` wiederholbar) kam in +Stufe 3 nicht vor — er steckt nur an +`POST /transactions/{id}/transfer`, also in Stufe 4. Dort wird er gebraucht: +Die App muss den Hinweis zeigen und den Aufruf auf Wunsch wiederholen, +statt den Fehler bloss zu melden. Stufe 7 steht bewusst am Ende. Alles davor ist für sich nutzbar. Der Ablauf hat **keinen Server-Zustand** zwischen den Schritten: Die Datei wird bei jedem