GET /wiedervorlage (Ebene 3) zeigt aktive Genehmigungen, die erneut geprüft werden sollten: Ablaufdatum erreicht oder innerhalb von 30 Tagen, das zugesagte Werkzeug wurde aus dem Katalog entfernt, oder der aktuelle Katalogeintrag weicht bei AVV/Training-Standard/ Verarbeitungsort vom zum Entscheidungszeitpunkt eingefrorenen Snapshot ab. Keine E-Mail-Infrastruktur vorhanden — Benachrichtigung ist bewusst eine In-App-Liste. Damit ist die ursprüngliche Baureihenfolge (Schritt 1-7) vollständig umgesetzt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
105 lines
3.6 KiB
Go
105 lines
3.6 KiB
Go
// 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)
|
|
}
|
|
}
|