Files
chatwoot/app/services/assignment_v2/assignment_service.rb
T

113 lines
3.0 KiB
Ruby

# frozen_string_literal: true
class AssignmentV2::AssignmentService
pattr_initialize [:inbox!]
def perform_for_conversation(conversation)
return false unless can_assign?(conversation)
agent = find_agent_for_conversation(conversation)
return false unless agent
assign_conversation_to_agent(conversation, agent)
end
def perform_bulk_assignment(limit: 50)
return 0 unless assignment_enabled?
conversations = unassigned_conversations(limit)
assigned_count = 0
conversations.find_each do |conversation|
assigned_count += 1 if perform_for_conversation(conversation)
end
assigned_count
end
private
def policy
@policy ||= inbox.assignment_policy
end
def assignment_enabled?
policy&.enabled?
end
def can_assign?(conversation)
assignment_enabled? &&
conversation.status == 'open' &&
conversation.assignee_id.nil?
end
def find_agent_for_conversation(_conversation)
available_agents = inbox.available_agents(check_rate_limits: true)
if available_agents.empty?
log_no_agents_available
return nil
end
selector_service.select_agent(available_agents)
end
def selector_service
@selector_service ||= if policy.assignment_order == 'balanced' && enterprise_enabled? && policy.can_use_balanced_assignment?
Enterprise::AssignmentV2::BalancedSelector.new(inbox: inbox)
else
AssignmentV2::RoundRobinSelector.new(inbox: inbox)
end
end
def unassigned_conversations(limit)
scope = inbox.conversations
.unassigned
.open
# Apply conversation priority ordering
scope = case policy.conversation_priority
when 'longest_waiting'
scope.order(last_activity_at: :asc, created_at: :asc)
else
scope.order(created_at: :asc)
end
scope.limit(limit)
end
def assign_conversation_to_agent(conversation, agent)
conversation.update!(assignee: agent)
create_assignment_activity(conversation, agent)
record_assignment_in_rate_limiter(conversation, agent)
true
rescue ActiveRecord::RecordInvalid => e
Rails.logger.error "AssignmentV2: Failed to assign conversation #{conversation.id}: #{e.message}"
false
end
def create_assignment_activity(conversation, agent)
Rails.configuration.dispatcher.dispatch(
ASSIGNEE_CHANGED,
Time.zone.now,
conversation: conversation,
user: agent
)
end
def enterprise_enabled?
@enterprise_enabled ||= defined?(Enterprise)
end
def log_no_agents_available
Rails.logger.warn("AssignmentV2: No agents available for inbox #{inbox.id}")
end
def record_assignment_in_rate_limiter(conversation, agent)
rate_limiter = AssignmentV2::RateLimiter.new(inbox: inbox, user: agent)
rate_limiter.record_assignment(conversation)
rescue StandardError => e
Rails.logger.error "AssignmentV2: Failed to record assignment in rate limiter: #{e.message}"
end
end