feat(reports): align summary aggregates
This commit is contained in:
@@ -121,6 +121,18 @@ func parseReportTimezoneOffset(c *gin.Context) (float64, bool) {
|
||||
return 0, true
|
||||
}
|
||||
|
||||
func parseOptionalReportID(c *gin.Context) (uint, bool) {
|
||||
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 0, false
|
||||
}
|
||||
return uint(parsed), true
|
||||
}
|
||||
return 0, true
|
||||
}
|
||||
|
||||
func parseConversationTrafficRange(c *gin.Context) (time.Time, time.Time, float64, bool) {
|
||||
timezoneOffset, ok := parseReportTimezoneOffset(c)
|
||||
if !ok {
|
||||
@@ -210,8 +222,15 @@ func (h *AnalyticsHandler) Summary(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if _, ok := parseReportTimezoneOffset(c); !ok {
|
||||
return
|
||||
}
|
||||
id, ok := parseOptionalReportID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
result, err := h.svc.GetSummary(c.Request.Context(), accountID, since, until)
|
||||
result, err := h.svc.GetReportSummary(c.Request.Context(), accountID, since, until, c.DefaultQuery("type", "account"), id, parseReportBusinessHours(c))
|
||||
if err != nil {
|
||||
applogger.L().Errorf("Summary report: %v", err)
|
||||
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, "failed to generate summary report")
|
||||
@@ -370,8 +389,12 @@ func (h *AnalyticsHandler) BotSummary(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
id, ok := parseOptionalReportID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
result, err := h.svc.GetBotSummary(c.Request.Context(), accountID, since, until)
|
||||
result, err := h.svc.GetBotSummary(c.Request.Context(), accountID, since, until, c.DefaultQuery("type", "account"), id)
|
||||
if err != nil {
|
||||
applogger.L().Errorf("Bot summary report: %v", err)
|
||||
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, "failed to generate bot summary")
|
||||
|
||||
@@ -145,16 +145,24 @@ func (s *AnalyticsHandlerTestSuite) TestSummary_EmptyData() {
|
||||
var body map[string]interface{}
|
||||
s.NoError(json.Unmarshal(w.Body.Bytes(), &body))
|
||||
s.NotContains(body, "success")
|
||||
s.NotNil(body["metrics"])
|
||||
s.Equal(float64(0), body["conversations_count"])
|
||||
s.Equal(float64(0), body["incoming_messages_count"])
|
||||
s.Equal(float64(0), body["outgoing_messages_count"])
|
||||
s.NotNil(body["previous"])
|
||||
}
|
||||
|
||||
func (s *AnalyticsHandlerTestSuite) TestSummary_WithData() {
|
||||
// Seed a reporting event
|
||||
conv := model.Conversation{AccountID: s.accountID, InboxID: 1, ContactID: 1, Status: string(model.ConversationStatusResolved), ChannelType: "web_widget", Channel: "web_widget", Base: model.Base{CreatedAt: parseTime("2025-01-15T10:00:00Z")}}
|
||||
s.Require().NoError(s.db.Create(&conv).Error)
|
||||
outgoing := model.Message{AccountID: s.accountID, InboxID: 1, ConversationID: conv.ID, MessageType: string(model.MessageTypeOutgoing), Content: "hello", Base: model.Base{CreatedAt: parseTime("2025-01-15T10:01:00Z")}}
|
||||
s.Require().NoError(s.db.Create(&outgoing).Error)
|
||||
ev := model.ReportingEvent{
|
||||
Base: model.Base{CreatedAt: parseTime("2025-01-15T10:02:00Z")},
|
||||
AccountID: s.accountID,
|
||||
Name: "first_response",
|
||||
Value: 120.5,
|
||||
ValueInBusinessHours: 60.0,
|
||||
ConversationID: &conv.ID,
|
||||
EventStartTime: parseTime("2025-01-15T10:00:00Z"),
|
||||
EventEndTime: parseTime("2025-01-15T10:02:00Z"),
|
||||
}
|
||||
@@ -165,6 +173,12 @@ func (s *AnalyticsHandlerTestSuite) TestSummary_WithData() {
|
||||
"/api/v1/accounts/1/reports/summary?since=2025-01-01T00:00:00Z&until=2025-02-01T00:00:00Z", nil)
|
||||
s.router.ServeHTTP(w, req)
|
||||
s.Equal(http.StatusOK, w.Code)
|
||||
var body map[string]interface{}
|
||||
s.NoError(json.Unmarshal(w.Body.Bytes(), &body))
|
||||
s.Equal(float64(1), body["conversations_count"])
|
||||
s.Equal(float64(1), body["outgoing_messages_count"])
|
||||
s.Equal(120.5, body["avg_first_response_time"])
|
||||
s.Contains(body, "previous")
|
||||
}
|
||||
|
||||
func (s *AnalyticsHandlerTestSuite) TestIndex_TimeseriesWithData() {
|
||||
|
||||
Reference in New Issue
Block a user