feat(reports): align first response distribution range

This commit is contained in:
2026-06-07 01:49:30 +08:00
parent 2453a84098
commit dd23de4e53
5 changed files with 66 additions and 6 deletions
+20 -1
View File
@@ -566,7 +566,7 @@ func (h *AnalyticsHandler) FirstResponseTimeDistribution(c *gin.Context) {
if !ok {
return
}
since, until, ok := parseDateRange(c)
since, until, ok := parseOptionalReportDateRange(c)
if !ok {
return
}
@@ -581,6 +581,25 @@ func (h *AnalyticsHandler) FirstResponseTimeDistribution(c *gin.Context) {
c.JSON(http.StatusOK, result)
}
func parseOptionalReportDateRange(c *gin.Context) (since, until time.Time, ok bool) {
sinceRaw := c.Query("since")
untilRaw := c.Query("until")
if sinceRaw == "" || untilRaw == "" {
return time.Time{}, time.Time{}, true
}
since, err := parseChatwootReportTime(sinceRaw)
if err != nil {
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid since date format")
return time.Time{}, time.Time{}, false
}
until, err = parseChatwootReportTime(untilRaw)
if err != nil {
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid until date format")
return time.Time{}, time.Time{}, false
}
return since, until, true
}
// OutgoingMessagesCount returns outgoing message count metrics.
// GET /api/v1/accounts/:account_id/reports/outgoing_messages_count
// Reference: Chatwoot reports#outgoing_messages_count
@@ -74,6 +74,7 @@ func (s *AnalyticsHandlerTestSuite) SetupSuite() {
accounts.GET("/reports/conversation_traffic", s.handler.ConversationTraffic)
accounts.GET("/reports/conversations", s.handler.Conversations)
accounts.GET("/reports/conversations_summary", s.handler.ConversationsSummary)
accounts.GET("/reports/first_response_time_distribution", s.handler.FirstResponseTimeDistribution)
accounts.GET("/reports/inbox_label_matrix", s.handler.InboxLabelMatrix)
accounts.GET("/reports/outgoing_messages_count", s.handler.OutgoingMessagesCount)
s.router = r
@@ -514,6 +515,21 @@ func (s *AnalyticsHandlerTestSuite) TestOutgoingMessagesCount_InvalidGroupByRetu
s.Empty(w.Body.String())
}
func (s *AnalyticsHandlerTestSuite) TestFirstResponseTimeDistribution_AllowsMissingRange() {
inbox := model.Inbox{AccountID: s.accountID, Name: "Web", ChannelType: "web_widget", ChannelID: 1, Enabled: true}
s.Require().NoError(s.db.Create(&inbox).Error)
s.Require().NoError(s.db.Create(&model.ReportingEvent{AccountID: s.accountID, Name: model.MetricNameFirstResponse, Value: 4000, InboxID: &inbox.ID}).Error)
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/api/v1/accounts/1/reports/first_response_time_distribution", nil)
s.router.ServeHTTP(w, req)
s.Equal(http.StatusOK, w.Code)
var payload map[string]map[string]int64
s.Require().NoError(json.Unmarshal(w.Body.Bytes(), &payload))
s.Equal(int64(1), payload["web_widget"]["1-4h"])
}
// ========== Nil service guard ==========
func (s *AnalyticsHandlerTestSuite) TestNilService() {