feat(conversations): align standard filters

This commit is contained in:
2026-06-07 04:51:20 +08:00
parent f8d326ca2a
commit 576239b842
3 changed files with 245 additions and 10 deletions
@@ -1217,6 +1217,142 @@ func (s *ConversationCrudTestSuite) TestFilter_ChatwootPayloadCustomAttributeNot
assert.ElementsMatch(s.T(), []float64{float64(silverID), float64(nilID)}, ids)
}
func (s *ConversationCrudTestSuite) TestFilter_ChatwootPayloadStandardPresenceFilters() {
agentID := uint(7001)
teamID := uint(7002)
campaignID := uint(7003)
s.testConv.AssigneeID = &agentID
s.testConv.TeamID = &teamID
s.testConv.CampaignID = &campaignID
s.Require().NoError(s.db.Save(s.testConv).Error)
unassigned := &model.Conversation{AccountID: s.testAccount.ID, InboxID: s.testInbox.ID, ContactID: s.testContact.ID, Status: "open", ChannelType: "web_widget", Channel: "web_widget"}
s.Require().NoError(s.db.Create(unassigned).Error)
body, _ := json.Marshal(map[string]interface{}{
"payload": []map[string]interface{}{
{"attribute_key": "assignee_id", "filter_operator": "is_present", "values": []string{}, "query_operator": "AND"},
{"attribute_key": "team_id", "filter_operator": "equal_to", "values": []string{"7002"}, "query_operator": "AND"},
{"attribute_key": "campaign_id", "filter_operator": "is_present", "values": []string{}},
},
})
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", s.accountURL()+"/conversations/filter", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
s.router.ServeHTTP(w, req)
assert.Equal(s.T(), http.StatusOK, w.Code)
var resp struct {
Meta struct {
AllCount int64 `json:"all_count"`
} `json:"meta"`
Payload []map[string]interface{} `json:"payload"`
}
s.Require().NoError(json.Unmarshal(w.Body.Bytes(), &resp))
assert.Equal(s.T(), int64(1), resp.Meta.AllCount)
s.Require().Len(resp.Payload, 1)
assert.Equal(s.T(), float64(s.testConv.ID), resp.Payload[0]["id"])
}
func (s *ConversationCrudTestSuite) TestFilter_ChatwootPayloadLabels() {
vip := &model.Tag{AccountID: s.testAccount.ID, Name: "vip", Color: "#1f93ff"}
s.Require().NoError(s.db.Create(vip).Error)
s.Require().NoError(s.db.Create(&model.ConversationLabel{AccountID: s.testAccount.ID, ConversationID: s.testConv.ID, TagID: vip.ID}).Error)
plainID := uint(33303)
plain := &model.Conversation{AccountID: s.testAccount.ID, InboxID: s.testInbox.ID, ContactID: s.testContact.ID, DisplayID: &plainID, Status: "open", ChannelType: "web_widget", Channel: "web_widget"}
s.Require().NoError(s.db.Create(plain).Error)
body, _ := json.Marshal(map[string]interface{}{
"payload": []map[string]interface{}{
{"attribute_key": "labels", "filter_operator": "equal_to", "values": []string{"vip"}},
},
})
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", s.accountURL()+"/conversations/filter", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
s.router.ServeHTTP(w, req)
assert.Equal(s.T(), http.StatusOK, w.Code)
var resp struct {
Meta struct {
AllCount int64 `json:"all_count"`
} `json:"meta"`
Payload []map[string]interface{} `json:"payload"`
}
s.Require().NoError(json.Unmarshal(w.Body.Bytes(), &resp))
assert.Equal(s.T(), int64(1), resp.Meta.AllCount)
s.Require().Len(resp.Payload, 1)
assert.Equal(s.T(), float64(s.testConv.ID), resp.Payload[0]["id"])
}
func (s *ConversationCrudTestSuite) TestFilter_ChatwootPayloadDisplayIDContainsAndDate() {
primaryID := uint(45678)
s.testConv.DisplayID = &primaryID
s.Require().NoError(s.db.Save(s.testConv).Error)
s.Require().NoError(s.db.Model(&model.Conversation{}).Where("id = ?", s.testConv.ID).Update("created_at", time.Date(2024, 1, 20, 10, 0, 0, 0, time.UTC)).Error)
olderID := uint(12345)
older := &model.Conversation{AccountID: s.testAccount.ID, InboxID: s.testInbox.ID, ContactID: s.testContact.ID, DisplayID: &olderID, Status: "open", ChannelType: "web_widget", Channel: "web_widget"}
s.Require().NoError(s.db.Create(older).Error)
s.Require().NoError(s.db.Model(&model.Conversation{}).Where("id = ?", older.ID).Update("created_at", time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC)).Error)
body, _ := json.Marshal(map[string]interface{}{
"payload": []map[string]interface{}{
{"attribute_key": "display_id", "filter_operator": "contains", "values": []string{"567"}, "query_operator": "AND"},
{"attribute_key": "created_at", "filter_operator": "is_greater_than", "values": []string{"2024-01-10"}},
},
})
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", s.accountURL()+"/conversations/filter", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
s.router.ServeHTTP(w, req)
assert.Equal(s.T(), http.StatusOK, w.Code)
var resp struct {
Meta struct {
AllCount int64 `json:"all_count"`
} `json:"meta"`
Payload []map[string]interface{} `json:"payload"`
}
s.Require().NoError(json.Unmarshal(w.Body.Bytes(), &resp))
assert.Equal(s.T(), int64(1), resp.Meta.AllCount)
s.Require().Len(resp.Payload, 1)
assert.Equal(s.T(), float64(primaryID), resp.Payload[0]["id"])
}
func (s *ConversationCrudTestSuite) TestFilter_ChatwootPayloadLastActivityAtDaysBefore() {
recentActivity := time.Now().UTC().AddDate(0, 0, -1).Unix()
oldActivity := time.Now().UTC().AddDate(0, 0, -12).Unix()
s.testConv.LastActivityAt = &oldActivity
s.Require().NoError(s.db.Save(s.testConv).Error)
recent := &model.Conversation{AccountID: s.testAccount.ID, InboxID: s.testInbox.ID, ContactID: s.testContact.ID, Status: "open", LastActivityAt: &recentActivity, ChannelType: "web_widget", Channel: "web_widget"}
s.Require().NoError(s.db.Create(recent).Error)
body, _ := json.Marshal(map[string]interface{}{
"payload": []map[string]interface{}{
{"attribute_key": "last_activity_at", "filter_operator": "days_before", "values": []string{"7"}},
},
})
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", s.accountURL()+"/conversations/filter", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
s.router.ServeHTTP(w, req)
assert.Equal(s.T(), http.StatusOK, w.Code)
var resp struct {
Meta struct {
AllCount int64 `json:"all_count"`
} `json:"meta"`
Payload []map[string]interface{} `json:"payload"`
}
s.Require().NoError(json.Unmarshal(w.Body.Bytes(), &resp))
assert.Equal(s.T(), int64(1), resp.Meta.AllCount)
s.Require().Len(resp.Payload, 1)
assert.Equal(s.T(), float64(s.testConv.ID), resp.Payload[0]["id"])
}
func (s *ConversationCrudTestSuite) TestFilter_ChatwootPayloadInvalidQueryOperator() {
body, _ := json.Marshal(map[string]interface{}{
"payload": []map[string]interface{}{