feat(reports): add analytics timeseries rollups

This commit is contained in:
2026-06-05 21:14:45 +08:00
parent a48b9cda8e
commit 43aa2f81eb
11 changed files with 494 additions and 32 deletions
@@ -2,6 +2,7 @@ package v1
import (
"net/http"
"strconv"
"time"
"github.com/gin-gonic/gin"
@@ -21,6 +22,41 @@ func NewAnalyticsHandler(svc *service.AnalyticsService) *AnalyticsHandler {
return &AnalyticsHandler{svc: svc}
}
// Index returns metric time-series for the overview charts.
// GET /api/v2/accounts/:account_id/reports?metric=...&since=...&until=...
func (h *AnalyticsHandler) Index(c *gin.Context) {
accountID, ok := parseAccountID(c)
if !ok {
return
}
since, until, ok := parseDateRange(c)
if !ok {
return
}
metric := c.Query("metric")
if metric == "" {
response.AbortWithStatusError(c, http.StatusUnprocessableEntity, response.ErrBadRequest, "metric parameter is required")
return
}
id := uint(0)
if rawID := c.Query("id"); rawID != "" {
parsed, err := strconv.ParseUint(rawID, 10, 64)
if err != nil {
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid id")
return
}
id = uint(parsed)
}
businessHours := c.Query("business_hours") == "true" || c.Query("business_hours") == "1"
result, err := h.svc.GetTimeseries(c.Request.Context(), accountID, metric, since, until, c.DefaultQuery("type", "account"), id, c.Query("group_by"), businessHours)
if err != nil {
applogger.L().Errorf("Timeseries report: %v", err)
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, "failed to generate report")
return
}
response.OK(c, result)
}
// parseAccountID extracts account_id from URL params.
func parseAccountID(c *gin.Context) (uint, bool) {
id := getAccountID(c)