From c86dfbfcee69062c3bd036a5070a6e62fb11e06c Mon Sep 17 00:00:00 2001 From: Özgür Kesim Date: Wed, 27 Nov 2024 17:03:50 +0100 Subject: totals per wp --- templates/report.t | 11 ++++----- zeitgeist.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/templates/report.t b/templates/report.t index d82b8bf..08f4f43 100644 --- a/templates/report.t +++ b/templates/report.t @@ -5,14 +5,13 @@ End: {{.End}} Beneficiary: {{.Beneficiary}} -# Calendar - -{{ range $y, $c := .Calendars }} -{{ $c }} +{{ range $wp, $t := .Totals }} +Total for {{ $wp }}: + - Budgeted: {{ printf "%8s" $t.Budgeted.AsDay }} + - Planned: {{ printf "%8s" $t.Planned.AsDay }}{{with $t.Unaccounted }} Unaccounted: {{.AsDay}}{{end}} + - Actual: {{ printf "%8s" $t.Actual.AsDay }} {{ end }} - - {{ range $id, $wp := .Workpackages -}} ## Workpackage {{ $id }}: {{ $wp.Title }} {{ range $tid, $task := $wp.Tasks }} diff --git a/zeitgeist.go b/zeitgeist.go index e20ad35..811de40 100644 --- a/zeitgeist.go +++ b/zeitgeist.go @@ -64,6 +64,32 @@ func (en Entries) WPs() string { return strings.Join(wps, ", ") } +func (en Entries) FilterWP(name string) Entries { + r := Entries{} + for _, e := range en { + if name == e.WP { + r = append(r, e) + } + } + return r +} + +func (en Entries) Totals() Amount { + var a Amount + for _, e := range en { + a += e.Amount + } + return a +} + +func (t Timeline) FilterWP(name string) Entries { + r := Entries{} + for _, entries := range t { + r = append(r, entries.FilterWP(name)...) + } + return r +} + type User struct { Name string Type string @@ -78,6 +104,14 @@ type Workpackage struct { Tasks map[string]Task } +func (wp *Workpackage) TotalBudget() Amount { + var a Amount + for _, t := range wp.Tasks { + a += t.Budget + } + return a +} + type Date time.Time func (d Date) IsWorkday() bool { @@ -292,7 +326,7 @@ func (p *Project) readPlans(dir string) error { } else { r[0], e = time.Parse("2006-01", parts[0]) if e == nil { - slog.Info("Month found", "date", parts[0]) + slog.Debug("Month found", "date", parts[0]) r[1] = r[0].AddDate(0, 1, 0) isrange = true } else { @@ -310,7 +344,7 @@ func (p *Project) readPlans(dir string) error { if r[0].Equal(r[1]) || r[0].After(r[1]) { return fmt.Errorf("file %q, line %d: invalid range: %s", name, nr, parts[0]) } - slog.Info("Found range", "start", r[0], "end", r[1]) + slog.Debug("Found range", "start", r[0], "end", r[1]) isrange = true } } @@ -712,3 +746,34 @@ func (p *Project) Calendars() map[int]string { } return r } + +type Totals struct { + Budgeted Amount + Planned Amount + Actual Amount +} + +func (t *Totals) Unaccounted() Amount { + return t.Budgeted - t.Planned +} + +func (p *Project) TotalWP(name string) (t *Totals, e error) { + wp, ok := p.Workpackages[name] + if !ok { + return nil, fmt.Errorf("no such workpackage handle: %q", name) + } + t = &Totals{ + Budgeted: wp.TotalBudget(), + Planned: p.Planned.FilterWP(name).Total(), + Actual: p.Timeline.FilterWP(name).Total(), + } + return t, nil +} + +func (p *Project) Totals() (t map[string]*Totals) { + t = make(map[string]*Totals) + for n := range p.Workpackages { + t[n], _ = p.TotalWP(n) + } + return t +} -- cgit v1.2.3