Files
patrickandClaude Sonnet 5.5 5b8c20777d refactor: Pruefgate-Pakete nach Funktion benannt, migration* gruppiert
- dms/ai/workflow: qa0x-Pakete nach internal/gates/<thema> verschoben, Paketname = Thema
- internal/migration{acl,audit,...} -> internal/migration/{acl,audit,...}
- Importpfade, Gate-Skripte und zwei relative Migrationspfade angepasst
- keine Logikaenderung; mail-Gates bewusst unveraendert (pfadabhaengig)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 12:44:21 +01:00

49 lines
1.3 KiB
Go

package migrationverify
import (
"fmt"
"sort"
"strings"
)
// RenderBericht erzeugt den deutschsprachigen Zeilenzahl-Abgleich-Bericht
// als Markdown-Tabelle, sortiert nach Tenant und Tabelle.
func RenderBericht(reports []TableReport) string {
sorted := append([]TableReport(nil), reports...)
sort.Slice(sorted, func(i, j int) bool {
if sorted[i].TenantSlug != sorted[j].TenantSlug {
return sorted[i].TenantSlug < sorted[j].TenantSlug
}
return sorted[i].Table < sorted[j].Table
})
var b strings.Builder
b.WriteString("# Zeilenzahl-Abgleich je Kerntabelle\n\n")
b.WriteString("| Tenant | Tabelle | Quelle | Ziel | Differenz | Erklaert | Status | Begruendung |\n")
b.WriteString("|---|---|---|---|---|---|---|---|\n")
for _, r := range sorted {
status := "OK"
if r.OffenerBefund() {
status = "OFFENER BEFUND"
}
reason := strings.Join(r.ExplainedReasons, "; ")
if reason == "" {
reason = "-"
}
fmt.Fprintf(&b, "| %s | %s | %d | %d | %d | %d | %s | %s |\n",
r.TenantSlug, r.Table, r.SourceCount, r.TargetCount, r.Diff(), r.ExplainedCount, status, reason)
}
return b.String()
}
// OffeneBefunde filtert alle Reports mit ungeklaerter Abweichung.
func OffeneBefunde(reports []TableReport) []TableReport {
var out []TableReport
for _, r := range reports {
if r.OffenerBefund() {
out = append(out, r)
}
}
return out
}