Align GoChat with Chatwoot frontend contracts
This commit is contained in:
@@ -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,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.
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user