package membership import ( "fmt" "fuj-management/go/internal/domain/reconcile" "io" "strings" "time" ) // printFeesTable writes a fixed-width adult-fees table to w. // Mirrors scripts/calculate_fees.py main(). // // Verify with: // // PYTHONPATH=scripts:. python scripts/calculate_fees.py func printFeesTable(w io.Writer, members []reconcile.Member, sortedMonths []string) { type row struct { name string fees map[string]reconcile.FeeData } var adults []row for _, m := range members { if m.Tier == "A" { adults = append(adults, row{name: m.Name, fees: m.Fees}) } } if len(adults) == 0 { fmt.Fprintln(w, "No data.") return } monthLabel := func(m string) string { t, err := time.Parse("2006-01", m) if err != nil { return m } return t.Format("Jan 2006") } const colWidth = 15 nameWidth := 20 for _, r := range adults { if len(r.name) > nameWidth { nameWidth = len(r.name) } } // separator length: nameWidth + N*(colWidth+3) where +3 is " | " sepLen := nameWidth + len(sortedMonths)*(colWidth+3) // Header row fmt.Fprintf(w, "%-*s", nameWidth, "Member") for _, m := range sortedMonths { fmt.Fprintf(w, " | %*s", colWidth, monthLabel(m)) } fmt.Fprintln(w) fmt.Fprintln(w, strings.Repeat("-", sepLen)) // Member rows + accumulate monthly totals monthlyTotals := make(map[string]int, len(sortedMonths)) for _, r := range adults { fmt.Fprintf(w, "%-*s", nameWidth, r.name) for _, m := range sortedMonths { fd := r.fees[m] monthlyTotals[m] += fd.Expected var cell string if fd.Attendance > 0 { cell = fmt.Sprintf("%d CZK (%d)", fd.Expected, fd.Attendance) } else { cell = "-" } fmt.Fprintf(w, " | %*s", colWidth, cell) } fmt.Fprintln(w) } // Totals row fmt.Fprintln(w, strings.Repeat("-", sepLen)) fmt.Fprintf(w, "%-*s", nameWidth, "TOTAL") for _, m := range sortedMonths { cell := fmt.Sprintf("%d CZK", monthlyTotals[m]) fmt.Fprintf(w, " | %*s", colWidth, cell) } fmt.Fprintln(w) }