H-337: fix Web Channel availability and realtime delivery (#60)
* H-337: fix Web Channel availability and realtime delivery * fix(widget): preserve realtime sender and activity contracts * fix(widget): keep realtime sender payloads consistent * fix(widget): make public message persistence atomic * fix(inbox): keep availability projection out of schema --------- Co-authored-by: Rogee <rogee@ipao.vip>
This commit is contained in:
@@ -41,10 +41,29 @@ func (r *InboxMemberRepo) FindByInboxAndUser(ctx context.Context, inboxID, userI
|
||||
|
||||
// FindByInbox retrieves all members (agents) assigned to an inbox.
|
||||
func (r *InboxMemberRepo) FindByInbox(ctx context.Context, inboxID uint) ([]model.InboxMember, error) {
|
||||
var ims []model.InboxMember
|
||||
err := r.withAgentPreloads(r.db.WithContext(ctx)).Where("inbox_id = ?", inboxID).
|
||||
Order("id ASC").Find(&ims).Error
|
||||
return ims, err
|
||||
type inboxMemberWithAvailability struct {
|
||||
model.InboxMember `gorm:"embedded"`
|
||||
AccountAvailability string `gorm:"column:account_availability"`
|
||||
}
|
||||
|
||||
var rows []inboxMemberWithAvailability
|
||||
err := r.withAgentPreloads(r.db.WithContext(ctx)).
|
||||
Model(&model.InboxMember{}).
|
||||
Select("inbox_members.*, COALESCE(account_users.availability, 'offline') AS account_availability").
|
||||
Joins("LEFT JOIN inboxes ON inboxes.id = inbox_members.inbox_id").
|
||||
Joins("LEFT JOIN account_users ON account_users.account_id = inboxes.account_id AND account_users.user_id = inbox_members.user_id AND account_users.deleted_at IS NULL").
|
||||
Where("inbox_members.inbox_id = ?", inboxID).
|
||||
Order("inbox_members.id ASC").Find(&rows).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ims := make([]model.InboxMember, len(rows))
|
||||
for i := range rows {
|
||||
ims[i] = rows[i].InboxMember
|
||||
ims[i].AccountAvailability = rows[i].AccountAvailability
|
||||
}
|
||||
return ims, nil
|
||||
}
|
||||
|
||||
// FindByUser retrieves all inboxes a user is assigned to.
|
||||
|
||||
@@ -103,11 +103,12 @@ func TestInboxMemberRepo_FindByInbox(t *testing.T) {
|
||||
db := setupTestDB(t, &model.InboxMember{})
|
||||
repo := NewInboxMemberRepo(db)
|
||||
|
||||
_, user1, inbox := createInboxMemberPrereqs(t, db)
|
||||
account, user1, inbox := createInboxMemberPrereqs(t, db)
|
||||
|
||||
// Create a second user
|
||||
user2 := &model.User{Name: "IMTestUser2", Email: "im2@example.com", Provider: "email"}
|
||||
require.NoError(t, db.Create(user2).Error)
|
||||
require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: user1.ID, Role: "agent", Availability: "online"}).Error)
|
||||
|
||||
im1 := &model.InboxMember{InboxID: inbox.ID, UserID: user1.ID, Role: "agent"}
|
||||
require.NoError(t, db.Create(im1).Error)
|
||||
@@ -121,6 +122,8 @@ func TestInboxMemberRepo_FindByInbox(t *testing.T) {
|
||||
// Verify User is preloaded
|
||||
assert.Equal(t, "IMTestUser", members[0].User.Name)
|
||||
assert.Equal(t, "IMTestUser2", members[1].User.Name)
|
||||
assert.Equal(t, "online", members[0].AccountAvailability)
|
||||
assert.Equal(t, "offline", members[1].AccountAvailability)
|
||||
|
||||
// Verify ordering by ID ASC
|
||||
assert.Equal(t, im1.ID, members[0].ID)
|
||||
@@ -240,4 +243,4 @@ func TestInboxMemberRepo_DeleteByInbox(t *testing.T) {
|
||||
members, err := repo.FindByInbox(context.Background(), inbox.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, members, 0)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user