feat(conversations): align filter query message types

This commit is contained in:
2026-06-07 06:53:41 +08:00
parent 5efe61f801
commit bd20e6d80f
3 changed files with 43 additions and 7 deletions
+11 -3
View File
@@ -836,10 +836,10 @@ func (s *ConversationService) Filter(ctx context.Context, accountID uint, userID
// 9. Filter by query (q) — 1:1 Chatwoot: filter_by_query
// Search messages.content ILIKE, restricted to incoming/outgoing message types
if params.Query != "" {
searchTerm := "%" + params.Query + "%"
searchClause, searchTerm := conversationMessageSearchClause(query, params.Query)
query = query.Joins("JOIN messages ON messages.conversation_id = conversations.id").
Where("messages.content ILIKE ?", searchTerm).
Where("messages.message_type IN ?", []int{0, 1}) // incoming=0, outgoing=1
Where(searchClause, searchTerm).
Where("messages.message_type IN ?", []string{string(model.MessageTypeIncoming), string(model.MessageTypeOutgoing)})
}
// 10. Filter by source_id — 1:1 Chatwoot: filter_by_source_id
@@ -898,6 +898,14 @@ func (s *ConversationService) Filter(ctx context.Context, accountID uint, userID
}, nil
}
func conversationMessageSearchClause(query *gorm.DB, value string) (string, string) {
term := "%" + value + "%"
if query != nil && query.Dialector != nil && query.Dialector.Name() != "postgres" {
return "LOWER(messages.content) LIKE ?", "%" + strings.ToLower(value) + "%"
}
return "messages.content ILIKE ?", term
}
func (s *ConversationService) applyConversationPermissionFilter(ctx context.Context, accountID, userID uint, query *gorm.DB) (*gorm.DB, error) {
if userID == 0 {
return query, nil
@@ -378,6 +378,31 @@ func TestConversationService_Filter_AllowsAdministratorAllInboxes(t *testing.T)
assert.Equal(t, int64(2), result.Count.AllCount)
}
func TestConversationService_Filter_QueryUsesStoredMessageTypeStrings(t *testing.T) {
svc, db := setupConversationService(t)
account := createConversationServiceTestAccount(t, db)
inbox := createConversationServiceTestInbox(t, db, account.ID)
contact := createConversationServiceTestContact(t, db, account.ID)
admin := &model.User{Name: "Filter Query Admin", Email: "filter-query-admin@example.com"}
require.NoError(t, db.Create(admin).Error)
require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: admin.ID, Role: "administrator"}).Error)
match := createConversationServiceTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
activityOnly := createConversationServiceTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
noMatch := createConversationServiceTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
require.NoError(t, db.Create(&model.Message{AccountID: account.ID, InboxID: inbox.ID, ConversationID: match.ID, Content: "Needle from customer", MessageType: string(model.MessageTypeIncoming)}).Error)
require.NoError(t, db.Create(&model.Message{AccountID: account.ID, InboxID: inbox.ID, ConversationID: activityOnly.ID, Content: "Needle activity", MessageType: string(model.MessageTypeActivity)}).Error)
require.NoError(t, db.Create(&model.Message{AccountID: account.ID, InboxID: inbox.ID, ConversationID: noMatch.ID, Content: "other", MessageType: string(model.MessageTypeIncoming)}).Error)
result, err := svc.Filter(context.Background(), account.ID, admin.ID, FilterParams{Query: "needle", AssigneeType: "all"}, 0, 25)
require.NoError(t, err)
require.Len(t, result.Conversations, 1)
assert.Equal(t, match.ID, result.Conversations[0].ID)
assert.Equal(t, int64(1), result.Count.AllCount)
}
// ========== MarkUnread Tests ==========
func TestConversationService_MarkUnread(t *testing.T) {