Add date and ticket filters plus entry list to the project time report.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-27 23:23:22 +01:00
co-authored by Cursor
parent 2061df63d4
commit 34ab3b9c5b
6 changed files with 368 additions and 8 deletions
+40
View File
@@ -2,6 +2,7 @@ package server
import (
"net/http"
"sort"
"task/internal/sqlite"
"task/internal/ticket"
@@ -29,11 +30,46 @@ func (s *Server) handleProjectReport(w http.ResponseWriter, r *http.Request) {
return
}
from, err := ticket.ParseReportDay(r.URL.Query().Get("from"))
if err != nil {
writeError(w, http.StatusBadRequest, err.Error())
return
}
toDay, err := ticket.ParseReportDay(r.URL.Query().Get("to"))
if err != nil {
writeError(w, http.StatusBadRequest, err.Error())
return
}
var toBound = toDay
if !toDay.IsZero() {
toBound = ticket.EndOfReportDay(toDay)
}
filter := ticket.TimeFilter{
From: from,
To: toBound,
TicketID: r.URL.Query().Get("ticketId"),
}
entries, err := s.Times.ListByProject(id)
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}
entries = ticket.FilterEntries(entries, filter)
sort.Slice(entries, func(i, j int) bool {
ai, aj := entries[i].Start, entries[j].Start
if ai.IsZero() {
ai = entries[i].End
}
if aj.IsZero() {
aj = entries[j].End
}
if !ai.Equal(aj) {
return ai.After(aj)
}
return entries[i].ID > entries[j].ID
})
tickets, err := s.Tickets.List(id)
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
@@ -64,5 +100,9 @@ func (s *Server) handleProjectReport(w http.ResponseWriter, r *http.Request) {
"totalDurationNs": int64(total),
"rows": out,
"entryCount": len(entries),
"entries": entries,
"from": r.URL.Query().Get("from"),
"to": r.URL.Query().Get("to"),
"ticketId": filter.TicketID,
})
}