feat(reports): align v2 timeseries timezones
This commit is contained in:
@@ -49,7 +49,11 @@ func (h *AnalyticsHandler) Index(c *gin.Context) {
|
||||
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)
|
||||
timezoneOffset, ok := parseReportTimezoneOffset(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
result, err := h.svc.GetTimeseries(c.Request.Context(), accountID, metric, since, until, c.DefaultQuery("type", "account"), id, c.Query("group_by"), timezoneOffset, businessHours)
|
||||
if err != nil {
|
||||
applogger.L().Errorf("Timeseries report: %v", err)
|
||||
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, "failed to generate report")
|
||||
@@ -105,15 +109,22 @@ func parseReportBusinessHours(c *gin.Context) bool {
|
||||
return c.Query("business_hours") == "true" || c.Query("business_hours") == "1"
|
||||
}
|
||||
|
||||
func parseConversationTrafficRange(c *gin.Context) (time.Time, time.Time, float64, bool) {
|
||||
timezoneOffset := 0.0
|
||||
func parseReportTimezoneOffset(c *gin.Context) (float64, bool) {
|
||||
if raw := c.Query("timezone_offset"); raw != "" {
|
||||
parsed, err := strconv.ParseFloat(raw, 64)
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid timezone_offset")
|
||||
return time.Time{}, time.Time{}, 0, false
|
||||
return 0, false
|
||||
}
|
||||
timezoneOffset = parsed
|
||||
return parsed, true
|
||||
}
|
||||
return 0, true
|
||||
}
|
||||
|
||||
func parseConversationTrafficRange(c *gin.Context) (time.Time, time.Time, float64, bool) {
|
||||
timezoneOffset, ok := parseReportTimezoneOffset(c)
|
||||
if !ok {
|
||||
return time.Time{}, time.Time{}, 0, false
|
||||
}
|
||||
|
||||
if c.Query("since") != "" || c.Query("until") != "" {
|
||||
|
||||
@@ -179,8 +179,27 @@ func (s *AnalyticsHandlerTestSuite) TestIndex_TimeseriesWithData() {
|
||||
s.Equal(http.StatusOK, w.Code)
|
||||
var data []interface{}
|
||||
s.NoError(json.Unmarshal(w.Body.Bytes(), &data))
|
||||
s.Len(data, 1)
|
||||
s.Equal(float64(1), data[0].(map[string]interface{})["value"])
|
||||
s.Len(data, 31)
|
||||
s.Equal(float64(1), data[14].(map[string]interface{})["value"])
|
||||
}
|
||||
|
||||
func (s *AnalyticsHandlerTestSuite) TestIndex_TimeseriesHonorsTimezoneOffset() {
|
||||
conv := model.Conversation{AccountID: s.accountID, InboxID: 1, ContactID: 1, Status: string(model.ConversationStatusOpen), ChannelType: "web_widget", Channel: "web_widget", Base: model.Base{CreatedAt: parseTime("2025-01-02T01:00:00Z")}}
|
||||
s.Require().NoError(s.db.Create(&conv).Error)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodGet,
|
||||
"/api/v1/accounts/1/reports?metric=conversations_count&since=1735689600&until=1735862400&type=account&group_by=day&timezone_offset=-8", nil)
|
||||
s.router.ServeHTTP(w, req)
|
||||
s.Equal(http.StatusOK, w.Code)
|
||||
var data []map[string]interface{}
|
||||
s.NoError(json.Unmarshal(w.Body.Bytes(), &data))
|
||||
s.Len(data, 3)
|
||||
loc := time.FixedZone("report", -8*3600)
|
||||
s.Equal(float64(time.Date(2024, 12, 31, 0, 0, 0, 0, loc).Unix()), data[0]["timestamp"])
|
||||
s.Equal(float64(time.Date(2025, 1, 1, 0, 0, 0, 0, loc).Unix()), data[1]["timestamp"])
|
||||
s.Equal(float64(0), data[0]["value"])
|
||||
s.Equal(float64(1), data[1]["value"])
|
||||
}
|
||||
|
||||
// ========== AgentMetrics ==========
|
||||
|
||||
Reference in New Issue
Block a user