diff options
author | Özgür Kesim <oec@kesim.org> | 2024-11-27 17:03:50 +0100 |
---|---|---|
committer | Özgür Kesim <oec@kesim.org> | 2024-11-27 17:03:50 +0100 |
commit | c86dfbfcee69062c3bd036a5070a6e62fb11e06c (patch) | |
tree | 5197971673381c539b39b0ff720d9d0659b161c7 /zeitgeist.go | |
parent | 2bb8dcc9f63fdc09acdc83186626525957a45f4d (diff) |
totals per wp
Diffstat (limited to 'zeitgeist.go')
-rw-r--r-- | zeitgeist.go | 69 |
1 files changed, 67 insertions, 2 deletions
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 +} |