Erstzulassung war in der App nicht speicherbar

Einstellungen.tsx fuehrt fuer die Erstzulassung einen eigenen Entwurf neben
`entwurf`. Zwei Stellen kannten ihn nicht: speichern() stieg in der ersten
Zeile aus, und die Speicherleiste haengt allein an `entwurf` - wer nur die
Erstzulassung aenderte, bekam also gar keinen Speichern-Knopf zu sehen und
verlor den Wert beim Verlassen der Seite. Damit blieb auch die
Hauptuntersuchung leer, die daraus abgeleitet wird. Das Panel speichert an
dieser Stelle sofort und war nie betroffen.

Dazu:

* Platzhalter beider Felder war MM/JJJJ, obwohl ein voller Tag gemeint ist -
  jetzt TT.MM.JJJJ. Die Monatsform bleibt lesbar, damit gespeicherte Werte
  wie "08/2026" gueltig bleiben.
* Das Tagesmuster nimmt jetzt Punkt oder Bindestrich, in beiden Codebasen
  wortgleich. "01-03-2025" ergab vorher still nichts. Unmoegliche Daten
  werden weiterhin abgewiesen, die ISO-Form nicht verwechselt.

Geprueft am laufenden System ueber die ganze Kette: eintragen, speichern,
Profildatei, dann App-Service, Panel-Service und Panel-Mein-Audi mit
uebereinstimmend 15.06.2027. 299 Tests gruen, 0 Tracebacks.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-05 10:31:53 +02:00
parent ddcd9396b0
commit 44dcb3c9d9
8 changed files with 113 additions and 9 deletions
+26
View File
@@ -178,3 +178,29 @@ describe("Datumsangaben aus dem Bestand", () => {
expect(monatJahr("08/2026")).toBe("August 2026")
})
})
/* Der Eigentümer hat die Erstzulassung am 05.09.2026 „mit Punkt oder Strich"
eingetragen und danach ein leeres HU-Feld vorgefunden. Die eigentliche
Ursache lag im Speicherweg (Einstellungen.tsx), aber eine still verworfene
Eingabe soll auch dann nicht entstehen, wenn jemand Bindestriche tippt. */
describe("Datum mit Bindestrich statt Punkt", () => {
it("liest 15-06-2024 wie 15.06.2024", () => {
expect(datum("15-06-2024")).toBe(datum("15.06.2024"))
expect(datum("15-06-2024")).toBe("15.06.2024")
})
it("nimmt auch die einstellige Schreibweise", () => {
expect(datum("1-3-2025")).toBe("01.03.2025")
})
it("weist ein unmögliches Datum weiterhin ab, egal mit welchem Trenner", () => {
// new Date(2025, 1, 31) wäre der 3. März - das darf kein Datum ergeben.
expect(datum("31-02-2025")).toBe("")
expect(datum("31.02.2025")).toBe("")
})
it("verwechselt die ISO-Schreibweise nicht damit", () => {
// 2025-03-01 ist Jahr-Monat-Tag, nicht Tag-Monat-Jahr.
expect(datum("2025-03-01")).toBe("01.03.2025")
})
})
+4 -1
View File
@@ -132,7 +132,10 @@ interface Zeitpunkt {
zwar nach Norm statt nach Gutduenken. */
const ISO = /^\d{4}-\d{2}-\d{2}([T ]|$)/
/* "1.3.2025" wie "01.03.2025". */
const DE_TAG = /^(\d{1,2})\.(\d{1,2})\.(\d{4})$/
// Bindestrich ist mitgemeint: der Eigentuemer hat am 05.09.2026 "mit Punkt
// oder Strich" eingetragen. Eine still verworfene Eingabe ist der schlechtere
// Ausgang - der Platzhalter nennt trotzdem TT.MM.JJJJ als die gemeinte Form.
const DE_TAG = /^(\d{1,2})[.\-](\d{1,2})[.\-](\d{4})$/
/* "08/2026" und "08.2026" - Monat und Jahr, ohne Tag. */
const DE_MONAT = /^(\d{1,2})[./](\d{4})$/
/* "2026-08" - dieselbe Genauigkeit, in ISO-Schreibweise. */
+20 -4
View File
@@ -236,8 +236,16 @@ export function Einstellungen({
eigenen Entwurf und uebergibt ihn erst beim Druck auf Speichern. Ohne den
Umweg wuerde `entwurf` im selben Rendern noch den alten Wert tragen -
setState wirkt erst beim naechsten Durchlauf. */
/* `erstzulassung` fuehrt einen EIGENEN Entwurf, unabhaengig von
`entwurf` - es gehoert zum Fahrzeug, nicht zu den Einstellungen. Diese
Bedingung hat es dabei vergessen: wer nur die Erstzulassung aenderte,
kam hier nie vorbei, und weiter unten erschien auch die Speicherleiste
nicht (die haengt ebenfalls allein an `entwurf`). Der eingetippte Wert
war damit gar nicht speicherbar und beim Verlassen der Seite weg -
gemeldet vom Eigentuemer am 05.09.2026. Das Panel speichert an dieser
Stelle sofort bei jeder Aenderung und war deshalb nie betroffen. */
const speichern = async (zusatz?: Partial<EinstellungenWerte>) => {
if (!entwurf && !zusatz) return
if (!entwurf && !zusatz && erstzulassung === null) return
setzeLaeuft(true)
setzeGespeichert(false)
try {
@@ -398,7 +406,7 @@ export function Einstellungen({
<Feld label="Erstzulassung">
<input
className="dm-eingabe"
placeholder="MM/JJJJ"
placeholder="TT.MM.JJJJ"
value={erstzulassungWert}
onChange={(e) => setzeErstzulassung(e.target.value)}
/>
@@ -1009,9 +1017,17 @@ export function Einstellungen({
)}
{gespeichert && <p className="dm-erfolg">Gespeichert.</p>}
{entwurf && (
{(entwurf || erstzulassung !== null) && (
<div className="dm-speicherleiste">
<ActionButton onClick={() => setzeEntwurf(null)} disabled={laeuft}>
<ActionButton
onClick={() => {
setzeEntwurf(null)
// Sonst bliebe die Leiste nach "Verwerfen" stehen, weil der
// Erstzulassungs-Entwurf sie weiter offen haelt.
setzeErstzulassung(null)
}}
disabled={laeuft}
>
Verwerfen
</ActionButton>
<ActionButton variant="primary" onClick={() => void speichern()} disabled={laeuft}>