diff --git a/app/models/concerns/auto_assignment_handler.rb b/app/models/concerns/auto_assignment_handler.rb index a1198200a..dca154842 100644 --- a/app/models/concerns/auto_assignment_handler.rb +++ b/app/models/concerns/auto_assignment_handler.rb @@ -19,10 +19,18 @@ module AutoAssignmentHandler AutoAssignment::AssignmentJob.perform_later(inbox_id: inbox.id) else # Use legacy assignment system - AutoAssignment::AgentAssignmentService.new(conversation: self, allowed_agent_ids: inbox.member_ids_with_assignment_capacity).perform + # If conversation has a team, only consider team members for assignment + allowed_agent_ids = team_id.present? ? team_member_ids_with_capacity : inbox.member_ids_with_assignment_capacity + AutoAssignment::AgentAssignmentService.new(conversation: self, allowed_agent_ids: allowed_agent_ids).perform end end + def team_member_ids_with_capacity + return [] if team.blank? || team.allow_auto_assign.blank? + + inbox.member_ids_with_assignment_capacity & team.members.ids + end + def should_run_auto_assignment? return false unless inbox.enable_auto_assignment? diff --git a/app/services/auto_assignment/assignment_service.rb b/app/services/auto_assignment/assignment_service.rb index 5d75c515f..89eff9d1c 100644 --- a/app/services/auto_assignment/assignment_service.rb +++ b/app/services/auto_assignment/assignment_service.rb @@ -19,7 +19,7 @@ class AutoAssignment::AssignmentService def perform_for_conversation(conversation) return false unless assignable?(conversation) - agent = find_available_agent + agent = find_available_agent(conversation) return false unless agent assign_conversation(conversation, agent) @@ -44,13 +44,26 @@ class AutoAssignment::AssignmentService scope.limit(limit) end - def find_available_agent - agents = filter_agents_by_rate_limit(inbox.available_agents) + def find_available_agent(conversation = nil) + agents = filter_agents_by_team(inbox.available_agents, conversation) + return nil if agents.nil? + + agents = filter_agents_by_rate_limit(agents) return nil if agents.empty? round_robin_selector.select_agent(agents) end + def filter_agents_by_team(agents, conversation) + return agents if conversation&.team_id.blank? + + team = conversation.team + return nil if team.blank? || team.allow_auto_assign.blank? + + team_member_ids = team.members.ids + agents.where(user_id: team_member_ids) + end + def filter_agents_by_rate_limit(agents) agents.select do |agent_member| rate_limiter = build_rate_limiter(agent_member.user) diff --git a/enterprise/app/services/enterprise/auto_assignment/assignment_service.rb b/enterprise/app/services/enterprise/auto_assignment/assignment_service.rb index 46422f9bc..66cdc31e5 100644 --- a/enterprise/app/services/enterprise/auto_assignment/assignment_service.rb +++ b/enterprise/app/services/enterprise/auto_assignment/assignment_service.rb @@ -14,8 +14,11 @@ module Enterprise::AutoAssignment::AssignmentService end # Extend agent finding to add capacity checks - def find_available_agent - agents = filter_agents_by_rate_limit(inbox.available_agents) + def find_available_agent(conversation = nil) + agents = filter_agents_by_team(inbox.available_agents, conversation) + return nil if agents.nil? + + agents = filter_agents_by_rate_limit(agents) agents = filter_agents_by_capacity(agents) if capacity_filtering_enabled? return nil if agents.empty? diff --git a/spec/controllers/api/v1/accounts/conversations_controller_spec.rb b/spec/controllers/api/v1/accounts/conversations_controller_spec.rb index 3c380c155..bc7b4097f 100644 --- a/spec/controllers/api/v1/accounts/conversations_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/conversations_controller_spec.rb @@ -330,6 +330,7 @@ RSpec.describe 'Conversations API', type: :request do context 'when it is an authenticated user who has access to the inbox' do before do create(:inbox_member, user: agent, inbox: inbox) + create(:team_member, user: agent, team: team) end it 'creates a new conversation' do diff --git a/spec/services/auto_assignment/assignment_service_spec.rb b/spec/services/auto_assignment/assignment_service_spec.rb index 2139e5e78..36a8c7816 100644 --- a/spec/services/auto_assignment/assignment_service_spec.rb +++ b/spec/services/auto_assignment/assignment_service_spec.rb @@ -307,5 +307,52 @@ RSpec.describe AutoAssignment::AssignmentService do end end end + + context 'with team assignments' do + let(:team) { create(:team, account: account, allow_auto_assign: true) } + let(:team_member) { create(:user, account: account, role: :agent, availability: :online) } + let(:rate_limiter) { instance_double(AutoAssignment::RateLimiter) } + + before do + create(:team_member, team: team, user: team_member) + create(:inbox_member, inbox: inbox, user: team_member) + + allow(OnlineStatusTracker).to receive(:get_available_users).and_return({ team_member.id.to_s => 'online' }) + + allow(AutoAssignment::RateLimiter).to receive(:new).and_return(rate_limiter) + allow(rate_limiter).to receive(:within_limit?).and_return(true) + allow(rate_limiter).to receive(:track_assignment) + + round_robin_selector = instance_double(AutoAssignment::RoundRobinSelector) + allow(AutoAssignment::RoundRobinSelector).to receive(:new).and_return(round_robin_selector) + allow(round_robin_selector).to receive(:select_agent).and_return(team_member) + end + + it 'assigns conversation with team to team member' do + conversation_with_team = create(:conversation, inbox: inbox, team: team, assignee: nil) + + service.perform_bulk_assignment(limit: 1) + + expect(conversation_with_team.reload.assignee).to eq(team_member) + end + + it 'skips assignment when team has allow_auto_assign false' do + team.update!(allow_auto_assign: false) + conversation_with_team = create(:conversation, inbox: inbox, team: team, assignee: nil) + + service.perform_bulk_assignment(limit: 1) + + expect(conversation_with_team.reload.assignee).to be_nil + end + + it 'skips assignment when no team members are available' do + allow(OnlineStatusTracker).to receive(:get_available_users).and_return({}) + conversation_with_team = create(:conversation, inbox: inbox, team: team, assignee: nil) + + service.perform_bulk_assignment(limit: 1) + + expect(conversation_with_team.reload.assignee).to be_nil + end + end end end