package autoassignment import ( "context" "testing" "time" "github.com/gochat/gochat/internal/channel" "github.com/gochat/gochat/internal/model" "github.com/stretchr/testify/require" ) func TestAutoAssignmentListenerUsesChannelEventIDs(t *testing.T) { db, rdb := setupFullAADB_Cov9(t) account, agent, inbox, conversation := seedAssignableConversation_Cov9(t, db) event := channel.NewChannelEvent(channel.EventConversationCreated, channel.ChannelWebWidget, account.ID, inbox.ID) event.ConversationID = conversation.ID require.NoError(t, NewAutoAssignmentListener(db, rdb).OnEvent(context.Background(), event)) require.NoError(t, db.First(conversation, conversation.ID).Error) require.Equal(t, &agent.ID, conversation.AssigneeID) } func TestAssignmentServiceUsesLinkedCurrentPolicy(t *testing.T) { db, rdb := setupFullAADB_Cov9(t) account, firstAgent, inbox, conversation := seedAssignableConversation_Cov9(t, db) secondAgent := &model.User{AccountID: account.ID, Name: "second", Email: "second-policy@example.com", Password: "p", Active: true, Available: true} require.NoError(t, db.Create(secondAgent).Error) require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: secondAgent.ID, Role: "agent"}).Error) require.NoError(t, db.Create(&model.InboxMember{InboxID: inbox.ID, UserID: secondAgent.ID, Role: "agent", AvailabilityStatus: "online"}).Error) contact := &model.Contact{AccountID: account.ID, Name: "load", Email: "load-policy@example.com"} require.NoError(t, db.Create(contact).Error) load := &model.Conversation{AccountID: account.ID, InboxID: inbox.ID, ContactID: contact.ID, AssigneeID: &firstAgent.ID, Status: string(model.ConversationStatusOpen)} require.NoError(t, db.Create(load).Error) require.NoError(t, db.Model(account).Update("feature_flags", `{"advanced_assignment":true}`).Error) policy := &model.AssignmentPolicy{AccountID: account.ID, Name: "Runtime", AssignmentOrder: 1, FairDistributionLimit: 100, FairDistributionWindow: 3600, Enabled: true} require.NoError(t, db.Create(policy).Error) require.NoError(t, db.Create(&model.InboxAssignmentPolicy{InboxID: inbox.ID, AssignmentPolicyID: policy.ID}).Error) service := NewAssignmentService(db, rdb) assigned, err := service.AssignConversation(context.Background(), conversation.ID, inbox.ID, account.ID) require.NoError(t, err) require.Equal(t, secondAgent.ID, assigned, "balanced policy should choose the least-loaded agent") policy.AssignmentOrder = 0 require.NoError(t, db.Save(policy).Error) next := &model.Conversation{AccountID: account.ID, InboxID: inbox.ID, ContactID: contact.ID, Status: string(model.ConversationStatusOpen)} require.NoError(t, db.Create(next).Error) assigned, err = service.AssignConversation(context.Background(), next.ID, inbox.ID, account.ID) require.NoError(t, err) require.Equal(t, firstAgent.ID, assigned, "round-robin policy should use the queue order") } func TestListenerAppliesConversationPriorityToInboxBacklog(t *testing.T) { db, rdb := setupFullAADB_Cov9(t) account, agent, inbox, newest := seedAssignableConversation_Cov9(t, db) now := time.Now().Unix() require.NoError(t, db.Model(newest).Update("last_activity_at", now).Error) contact := &model.Contact{AccountID: account.ID, Name: "old", Email: "old-policy@example.com"} require.NoError(t, db.Create(contact).Error) oldActivity := now - int64((2 * time.Hour).Seconds()) oldest := &model.Conversation{AccountID: account.ID, InboxID: inbox.ID, ContactID: contact.ID, Status: string(model.ConversationStatusOpen), LastActivityAt: &oldActivity} require.NoError(t, db.Create(oldest).Error) policy := &model.AssignmentPolicy{AccountID: account.ID, Name: "Oldest first", ConversationPriority: 1, FairDistributionLimit: 1, FairDistributionWindow: 3600, Enabled: true} require.NoError(t, db.Create(policy).Error) require.NoError(t, db.Create(&model.InboxAssignmentPolicy{InboxID: inbox.ID, AssignmentPolicyID: policy.ID}).Error) event := channel.NewChannelEvent(channel.EventConversationCreated, channel.ChannelWebWidget, account.ID, inbox.ID) event.ConversationID = newest.ID require.NoError(t, NewAutoAssignmentListener(db, rdb).OnEvent(context.Background(), event)) require.NoError(t, db.First(oldest, oldest.ID).Error) require.NoError(t, db.First(newest, newest.ID).Error) require.Equal(t, &agent.ID, oldest.AssigneeID) require.Nil(t, newest.AssigneeID) } func TestDisabledLinkedPolicyStopsAssignment(t *testing.T) { db, rdb := setupFullAADB_Cov9(t) account, _, inbox, conversation := seedAssignableConversation_Cov9(t, db) policy := &model.AssignmentPolicy{AccountID: account.ID, Name: "Paused", Enabled: true} require.NoError(t, db.Create(policy).Error) require.NoError(t, db.Model(policy).Update("enabled", false).Error) require.NoError(t, db.Create(&model.InboxAssignmentPolicy{InboxID: inbox.ID, AssignmentPolicyID: policy.ID}).Error) assigned, err := NewAssignmentService(db, rdb).AssignConversation(context.Background(), conversation.ID, inbox.ID, account.ID) require.NoError(t, err) require.Zero(t, assigned) }