// Ebene 3 — Wiedervorlage (Schritt 7 der Baureihenfolge, siehe // CLAUDE.md). Eine aktive Genehmigung muss erneut geprüft werden, wenn // entweder ihr Ablaufdatum erreicht/nah ist, oder sich im Katalog eine // Eigenschaft geändert hat, auf der sie beruhte. Es gibt keine E-Mail- // Infrastruktur — "Benachrichtigung" ist v1 eine In-App-Liste, kein // Versand. package web import ( "fmt" "net/http" "time" "github.com/netcell-it/deklarix/internal/store" ) // wiedervorlageSchwelle: eine Genehmigung erscheint schon vor ihrem // Ablauf in der Wiedervorlage, damit der/die Verantwortliche Zeit zum // Reagieren hat. const wiedervorlageSchwelle = 30 * 24 * time.Hour // werkzeugDiff vergleicht den zum Entscheidungszeitpunkt eingefrorenen // Werkzeug-Snapshot mit dem aktuellen Katalogstand und benennt jede für // die Bewertung relevante Eigenschaft, die sich seitdem geändert hat. func werkzeugDiff(snapshot, current store.Werkzeug) []string { var diffs []string if snapshot.AVVVerfuegbar != current.AVVVerfuegbar { diffs = append(diffs, fmt.Sprintf("AVV verfügbar: %v → %v", snapshot.AVVVerfuegbar, current.AVVVerfuegbar)) } if snapshot.TrainingStandard != current.TrainingStandard { diffs = append(diffs, fmt.Sprintf("Training standardmäßig aus: %v → %v", snapshot.TrainingStandard, current.TrainingStandard)) } if snapshot.Verarbeitungsort != current.Verarbeitungsort { diffs = append(diffs, fmt.Sprintf("Verarbeitungsort: %s → %s", snapshot.Verarbeitungsort, current.Verarbeitungsort)) } return diffs } type wiedervorlageItem struct { AntragID string Titel string Werkzeug string Gruende []string } type wiedervorlageListeData struct { Title string Nav navData Eintraege []wiedervorlageItem } // handleWiedervorlageListe zeigt alle aktiven Genehmigungen des // Mandanten, die erneut geprüft werden sollten — abgelaufen/bald // ablaufend oder mit einem seither im Katalog geänderten Werkzeug. // Genehmigungen ohne Grund zur Wiedervorlage werden nicht gezeigt. func (s *Server) handleWiedervorlageListe(w http.ResponseWriter, r *http.Request) { entscheidungen, err := s.store.ListAktiveGenehmigungenForAccount(r.Context(), currentUser(r).AccountID) if err != nil { http.Error(w, "Genehmigungen konnten nicht geladen werden: "+err.Error(), http.StatusInternalServerError) return } var data wiedervorlageListeData data.Title, data.Nav = "Wiedervorlage", navFor(r) for _, e := range entscheidungen { var gruende []string if e.GueltigBis != nil { if time.Now().After(*e.GueltigBis) { gruende = append(gruende, "Genehmigung ist abgelaufen (seit "+e.GueltigBis.Format("02.01.2006")+")") } else if time.Until(*e.GueltigBis) < wiedervorlageSchwelle { gruende = append(gruende, "Genehmigung läuft am "+e.GueltigBis.Format("02.01.2006")+" ab") } } werkzeugName := "" if e.WerkzeugID != nil { current, err := s.store.GetWerkzeug(r.Context(), *e.WerkzeugID) if err != nil { gruende = append(gruende, "Werkzeug wurde aus dem Katalog entfernt") } else { werkzeugName = current.Name if e.WerkzeugSnapshot != nil { gruende = append(gruende, werkzeugDiff(*e.WerkzeugSnapshot, current)...) } } } if len(gruende) == 0 { continue } antrag, err := s.store.GetAntrag(r.Context(), e.AntragID) if err != nil { continue } data.Eintraege = append(data.Eintraege, wiedervorlageItem{ AntragID: antrag.ID, Titel: antrag.Titel, Werkzeug: werkzeugName, Gruende: gruende, }) } if err := s.templates.ExecuteTemplate(w, "wiedervorlage-liste", data); err != nil { http.Error(w, "Seite konnte nicht gerendert werden", http.StatusInternalServerError) } }