package main import ( "fmt" "log" "net/http" "time" "github.com/pocketbase/dbx" "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/apis" "github.com/pocketbase/pocketbase/core" ) type Entry struct { Project string Start string End string } type Project struct { Id string Identifier string Name string } func main() { app := pocketbase.New() app.OnServe().BindFunc(func(e *core.ServeEvent) error { e.Router.GET("/api/hours/{organisation}/{year}/{month}", func(c *core.RequestEvent) error { year := c.Request.PathValue("year") month := c.Request.PathValue("month") organisation := c.Request.PathValue("organisation") projects := []Project{} entries := []Entry{} err := app.DB(). NewQuery("SELECT * FROM projects WHERE organisation = {:organisation}"). Bind(dbx.Params{ "organisation": organisation, }). All(&projects) if err != nil { return c.JSON(http.StatusOK, map[string]any{"hours": nil, "error": err}) } err = app.DB(). NewQuery("SELECT * FROM entries WHERE start >= {:start} AND end <= {:end} AND end != '' AND project IN (SELECT id FROM projects WHERE organisation = {:organisation})"). Bind(dbx.Params{ "start": fmt.Sprintf("%s-%s-01 00:00:00.000Z", year, month), "end": fmt.Sprintf("%s-%s-31 23:59:59.999Z", year, month), "organisation": organisation, }). All(&entries) if err != nil { return c.JSON(http.StatusOK, map[string]any{"hours": nil, "error": err}) } var projects_map map[string]string projects_map = make(map[string]string) for _, e := range projects { projects_map[e.Id] = fmt.Sprintf("(%s) %s", e.Identifier, e.Name) } var hours map[string]float64 hours = make(map[string]float64) for _, e := range entries { start, err := time.Parse("2006-01-02 15:04:05.000Z", e.Start) if err != nil { return c.JSON(http.StatusOK, map[string]any{"hours": nil, "error": fmt.Sprintf("time.Parse(%s)", e.Start)}) } end, err := time.Parse("2006-01-02 15:04:05.000Z", e.End) if err != nil { return c.JSON(http.StatusOK, map[string]any{"hours": nil, "error": fmt.Sprintf("time.Parse(%s)", e.End)}) } var entry_hours = end.Sub(start).Hours() project, project_exists := projects_map[e.Project] if !project_exists { return c.JSON(http.StatusOK, map[string]any{"hours": nil, "error": fmt.Sprintf("time.Parse(%s)", e.End)}) } if value, total_entry_exists := hours[project]; total_entry_exists { hours[project] = value + entry_hours } else { hours[project] = entry_hours } } return c.JSON(http.StatusOK, map[string]any{"hours": hours, "error": nil}) }).Bind(apis.RequireAuth()) return e.Next() }) if err := app.Start(); err != nil { log.Fatal(err) } }