Add ticket time tracking with reports and entry management.

Support start/stop timer, manual durations, grouped reports, and per-ticket edit/delete of time entries with undo.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Skruecken
2026-10-19 11:05:10 +02:00
co-authored by Cursor
parent 41feba11de
commit bfc1cbd4d9
23 changed files with 2149 additions and 94 deletions
+81
View File
@@ -0,0 +1,81 @@
package command
import (
"context"
"fmt"
"task/internal/ticket"
)
// AddTimeEntry creates a time entry; Undo deletes it.
type AddTimeEntry struct {
Store ticket.TimeStore
Entry ticket.TimeEntry
created ticket.TimeEntry
}
func (c *AddTimeEntry) Name() string { return "add time entry" }
func (c *AddTimeEntry) Execute(ctx context.Context) error {
_ = ctx
created, err := c.Store.Create(c.Entry)
if err != nil {
return err
}
c.created = created
c.Entry = created
return nil
}
func (c *AddTimeEntry) Undo(ctx context.Context) error {
_ = ctx
id := c.created.ID
if id == "" {
id = c.Entry.ID
}
if id == "" {
return fmt.Errorf("add time undo: missing entry id")
}
return c.Store.Delete(id)
}
// RemoveTimeEntry deletes a time entry; Undo restores the snapshot.
type RemoveTimeEntry struct {
Store ticket.TimeStore
Snapshot ticket.TimeEntry
}
func (c *RemoveTimeEntry) Name() string { return "remove time entry" }
func (c *RemoveTimeEntry) Execute(ctx context.Context) error {
_ = ctx
if c.Snapshot.ID == "" {
return fmt.Errorf("remove time: missing entry id")
}
return c.Store.Delete(c.Snapshot.ID)
}
func (c *RemoveTimeEntry) Undo(ctx context.Context) error {
_ = ctx
_, err := c.Store.Create(c.Snapshot)
return err
}
// UpdateTimeEntry applies a new entry state; Undo restores Before.
type UpdateTimeEntry struct {
Store ticket.TimeStore
Before ticket.TimeEntry
After ticket.TimeEntry
}
func (c *UpdateTimeEntry) Name() string { return "update time entry" }
func (c *UpdateTimeEntry) Execute(ctx context.Context) error {
_ = ctx
return c.Store.Update(c.After)
}
func (c *UpdateTimeEntry) Undo(ctx context.Context) error {
_ = ctx
return c.Store.Update(c.Before)
}