Align GoChat with Chatwoot frontend contracts

This commit is contained in:
2026-06-13 22:13:32 +08:00
parent 71abf58636
commit d884fdda0a
162 changed files with 9825 additions and 528 deletions
+20 -1
View File
@@ -109,6 +109,25 @@ func TestAccountRepo_UpdateActiveAt_OverwritesPrevious(t *testing.T) {
assert.WithinDuration(t, secondTime, *refreshed.ActiveAt, time.Second)
}
func TestAccountUserRepo_UpdateActiveAt_SetsCurrentTimestamp(t *testing.T) {
db := setupAccountExtensionTestDB(t)
ctx := context.Background()
repo := NewAccountUserRepo(db)
account := createAccountExtTestAccount(t, db)
user := createAccountExtTestUser(t, db, account.ID)
createAccountExtTestAccountUser(t, db, account.ID, user.ID)
startedAt := time.Now().UTC()
err := repo.UpdateActiveAt(ctx, account.ID, user.ID)
require.NoError(t, err)
var refreshed model.AccountUser
require.NoError(t, db.Where("account_id = ? AND user_id = ?", account.ID, user.ID).First(&refreshed).Error)
assert.NotNil(t, refreshed.ActiveAt)
assert.WithinDuration(t, startedAt, *refreshed.ActiveAt, 5*time.Second)
}
// ===========================================================================
// FindAccountUserByUserAndAccount tests
// ===========================================================================
@@ -136,4 +155,4 @@ func TestAccountRepo_FindAccountUserByUserAndAccount_NotFound(t *testing.T) {
_, err := repo.FindAccountUserByUserAndAccount(ctx, 9999, 9999)
assert.ErrorIs(t, err, gorm.ErrRecordNotFound)
}
}
+2 -1
View File
@@ -2,6 +2,7 @@ package repository
import (
"context"
"time"
"gorm.io/gorm"
@@ -116,7 +117,7 @@ func (r *AccountUserRepo) UpdateActiveAt(ctx context.Context, accountID, userID
return r.db.WithContext(ctx).
Model(&model.AccountUser{}).
Where("account_id = ? AND user_id = ?", accountID, userID).
Update("active_at", gorm.Expr("NOW()")).Error
Update("active_at", time.Now().UTC()).Error
}
// FindByAccountAndUserOrFail retrieves an AccountUser by accountID and userID.
+3 -2
View File
@@ -84,12 +84,12 @@ func (r *ContactRepo) Search(ctx context.Context, accountID uint, query string,
if query != "" {
if searchMode == search.SearchModeTrigram {
// pg_trgm fuzzy match on contact fields
condition = condition.Where("name % ? OR email % ? OR phone_number ILIKE ? OR identifier % ?",
condition = condition.Where("contacts.name % ? OR contacts.email % ? OR contacts.phone_number ILIKE ? OR contacts.identifier % ?",
query, query, query, query)
} else {
// Case-insensitive substring match that works on PostgreSQL and SQLite tests.
likeQuery := "%" + query + "%"
condition = condition.Where("LOWER(name) LIKE LOWER(?) OR LOWER(email) LIKE LOWER(?) OR LOWER(phone_number) LIKE LOWER(?) OR LOWER(identifier) LIKE LOWER(?)",
condition = condition.Where("LOWER(contacts.name) LIKE LOWER(?) OR LOWER(contacts.email) LIKE LOWER(?) OR LOWER(contacts.phone_number) LIKE LOWER(?) OR LOWER(contacts.identifier) LIKE LOWER(?)",
likeQuery, likeQuery, likeQuery, likeQuery)
}
}
@@ -194,6 +194,7 @@ func contactFeatureFlagEnabled(raw, flag string) bool {
func resolveContactSort(sort string) string {
allowedSorts := map[string]string{
"name": "contacts.name ASC",
"date": "contacts.created_at DESC",
"email": "contacts.email ASC",
"created_at": "contacts.created_at DESC",
"last_activity_at": "contacts.last_activity_at DESC NULLS LAST, contacts.id DESC",
+9 -1
View File
@@ -221,6 +221,14 @@ func (r *NotificationRepo) CountUnreadByUserAndAccount(ctx context.Context, user
return count, err
}
func (r *NotificationRepo) CountByUserAndAccount(ctx context.Context, userID, accountID uint) (int64, error) {
var count int64
err := r.db.WithContext(ctx).Model(&model.Notification{}).
Where("user_id = ? AND account_id = ?", userID, accountID).
Count(&count).Error
return count, err
}
// Snooze sets the snoozed_until timestamp and clears read_at for a notification.
// Returns the updated notification.
// Reference: Chatwoot notifications_controller.rb#snooze
@@ -261,7 +269,7 @@ func (r *NotificationRepo) Snooze(ctx context.Context, id, userID, accountID uin
func (r *NotificationRepo) MarkUnread(ctx context.Context, id, userID, accountID uint) (*model.Notification, error) {
result := r.db.WithContext(ctx).Model(&model.Notification{}).
Where("id = ? AND user_id = ? AND account_id = ?", id, userID, accountID).
Update("read_at", nil)
Updates(map[string]interface{}{"read_at": gorm.Expr("NULL")})
if result.Error != nil {
return nil, result.Error
}