113 lines
3.0 KiB
Ruby
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
|