Kompletten Ablauf einmal durchgespielt — echten Fehler dabei gefunden

Wunsch: "ich will dass du es abcheckst" — nicht Stück für Stück (das war
schon geprüft), sondern EINMAL DURCHGÄNGIG als ein zusammenhängender
Ablauf, so wie ein echter Auftrag tatsächlich läuft: Anfrage → Angebot
→ Zusage im Portal → Anzahlung → laufende Uhr → Benachrichtigung →
Arbeit → Restzahlung → Gegenprobe mit Abbruch.

test-kette.mjs bildet genau das ab, gegen die echten Funktionen aus
server-internal/, mit einer Wegwerf-Datenbank. 40 Prüfungen, alle grün.

DABEI GEFUNDEN: Der Liefertermin-Countdown im Portal prüfte nicht, ob
die Uhr überhaupt schon läuft. Ein frisch zugesagtes Projekt hat schon
ein termin_am (aus der Zusage vorgerechnet), aber uhr_start_am steht
noch auf null, solange die Anzahlung nicht da ist. Der Kunde hätte also
direkt nach der Zusage einen tickenden Countdown gesehen — und wenn die
Anzahlung eintrifft, wird der Termin ab dem Zahlungstag NEU berechnet
und springt dann sichtbar nach hinten. Das sieht aus wie ein Fehler,
auch wenn die Zahl rechnerisch stimmt: Kaum zu erklären, warum "noch 8
Tage" plötzlich wieder "noch 10 Tage" werden.

Jetzt zwei klar getrennte Zustände: Vor der Anzahlung steht "Startet,
sobald deine Anzahlung da ist — voraussichtlicher Liefertermin danach:
ca. {datum}" (kein Countdown, aber der Termin bleibt sichtbar, kein
Verstecken). Danach der echte Countdown. Fünf Sprachen ergänzt.

Nebenbei einen irreführenden Kommentar korrigiert: Ein neuer Kunde wird
beim Angebot-Senden SOFORT freigeschaltet (nicht erst bei Zusage, wie
der alte Kommentar behauptete) — sonst könnte er sich gar nicht
einloggen, um sein eigenes Angebot anzusehen. Der Code war richtig,
nur die Erklärung falsch, und mein erster Testentwurf ist genau darauf
hereingefallen.

Bei der Gelegenheit auch die bekannte better-sqlite3-Aussetzer-Eigenart
(zufälliger Absturz beim Prozessende, dokumentiert seit früheren
Commits) noch einmal eingegrenzt: Derselbe Import in test-angebote.mjs
brach mal nach "GEHEIM", mal nach "VORLAGEN" ab — der Absturzpunkt
verschiebt sich zwischen identischen Läufen. Das ist der endgültige
Beweis, dass es reine GC-Zeitfensterflakiness in der nativen
Bibliothek ist, kein Fehler im eigenen Code.

Geprüft: 40 (Kette) + 55 + 56 + 70 + 28 + 49 serverseitig (alle
mehrfach unabhängig grün), 261 im Browser (Portal, Angebot, Übersicht,
Verwaltung, Abbruch, Design). Ein Screenshot bestätigt den neuen
Wartehinweis visuell.
This commit is contained in:
2026-08-24 16:54:35 +02:00
parent e43375728c
commit 521f0d5a80
5 changed files with 354 additions and 6 deletions
+19 -3
View File
@@ -271,7 +271,7 @@ export function portalUebersicht(req, res) {
.prepare(
`SELECT id, nummer, titel, paket, status, naechster_schritt, wartet_auf,
preis_cent, anzahlung_cent, anzahlung_bezahlt, rest_bezahlt, waehrung,
start_am, richttermin, termin_am, angenommen_am, uebergabe_am, portfolio_freigabe
start_am, richttermin, termin_am, uhr_start_am, angenommen_am, uebergabe_am, portfolio_freigabe
FROM wd_projekte WHERE kunde_id = ? AND archiviert = 0
ORDER BY erstellt_am DESC`
)
@@ -299,11 +299,27 @@ export function portalUebersicht(req, res) {
Bei uebergebenen Projekten wird nicht mehr gezaehlt: Ein Countdown
auf etwas Fertiges wuerde irgendwann "ueberfaellig" anzeigen,
obwohl alles erledigt ist. */
obwohl alles erledigt ist.
GEFUNDEN beim Durchspielen der kompletten Kette am 24.08.2026: Die
Bedingung pruefte NICHT, ob die Uhr ueberhaupt schon laeuft. Ein
frisch zugesagtes Projekt hat schon ein termin_am (aus der Zusage
vorgerechnet), aber uhr_start_am steht noch auf null, solange die
Anzahlung nicht da ist. Ohne diese Pruefung saehe der Kunde direkt
nach der Zusage einen tickenden Countdown -- und wenn die Anzahlung
dann eintrifft, wird der Termin ab dem Zahlungstag NEU berechnet
und springt ploetzlich weiter nach hinten. Das sieht aus wie ein
Fehler, auch wenn es rechnerisch stimmt: Man kann einem Kunden
schwer erklaeren, warum "noch 8 Tage" ploetzlich wieder "noch 10
Tage" wurden. */
const uhrLaeuft = !!p.uhr_start_am;
const laeuftNoch = p.status !== "uebergeben" && p.status !== "abgebrochen";
p.verbleibende_werktage = (p.termin_am && laeuftNoch)
p.verbleibende_werktage = (p.termin_am && laeuftNoch && uhrLaeuft)
? werktageBis(p.termin_am, new Date())
: null;
/* Damit die Oberflaeche unterscheiden kann: "noch kein Termin",
"Termin steht, aber die Uhr laeuft noch nicht" und "laeuft". */
p.wartet_auf_anzahlung = !!p.termin_am && laeuftNoch && !uhrLaeuft;
}
/* Offene Angebote GANZ nach vorn.