207 lines
7.2 KiB
Ruby
207 lines
7.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# Test: Agent Capacity Limits (Enterprise)
|
|
# Run with: bundle exec rails runner script/assignment_v2/test_capacity_limits.rb
|
|
#
|
|
# Tests:
|
|
# - Agents respect inbox-specific capacity limits
|
|
# - When agent reaches limit, new conversations go to other agents
|
|
# - Agents without capacity policy have unlimited capacity
|
|
# - Capacity is per-inbox (agent can have different limits for different inboxes)
|
|
#
|
|
# Key Implementation Details:
|
|
# - AgentCapacityPolicy is linked to AccountUser (not User directly)
|
|
# - InboxCapacityLimit defines conversation_limit per inbox for a policy
|
|
# - CapacityService.agent_has_capacity? checks: current_open_conversations < limit
|
|
# - Enterprise::AutoAssignment::AssignmentService#filter_agents_by_capacity filters agents
|
|
# - Capacity filtering only happens when:
|
|
# 1. assignment_v2 feature is enabled
|
|
# 2. Account has at least one AccountUser with agent_capacity_policy
|
|
|
|
require_relative 'test_helpers'
|
|
|
|
class TestCapacityLimits
|
|
include AssignmentV2TestHelpers
|
|
|
|
def run
|
|
skip_if_not_enterprise
|
|
|
|
section('TEST: Agent Capacity Limits (Enterprise)')
|
|
|
|
account = get_test_account
|
|
inbox = nil
|
|
|
|
begin
|
|
# Setup test inbox and policy
|
|
inbox = create_test_inbox(account, name: 'Capacity Test Inbox')
|
|
policy = create_test_policy(account, name: 'Capacity Test Policy')
|
|
link_policy_to_inbox(inbox, policy)
|
|
|
|
# Test 1: Agents with capacity limits
|
|
section('Test 1: Agents Respect Capacity Limits')
|
|
|
|
# Create 2 agents
|
|
agent_limited = create_test_agent(account, inbox, name: 'Agent Limited', online: true)
|
|
agent_unlimited = create_test_agent(account, inbox, name: 'Agent Unlimited', online: true)
|
|
|
|
# Create capacity policy with limit of 3 conversations per agent for this inbox
|
|
capacity_policy = account.agent_capacity_policies.create!(
|
|
name: "Capacity Policy #{SecureRandom.hex(4)}",
|
|
exclusion_rules: {}
|
|
)
|
|
|
|
# Link capacity policy to the inbox with a limit of 3
|
|
capacity_policy.inbox_capacity_limits.create!(
|
|
inbox: inbox,
|
|
conversation_limit: 3
|
|
)
|
|
|
|
# Link capacity policy to agent_limited's account_user
|
|
account_user_limited = account.account_users.find_by(user: agent_limited)
|
|
account_user_limited.update!(agent_capacity_policy: capacity_policy)
|
|
|
|
info("#{agent_limited.name} has capacity limit of 3 for inbox #{inbox.id}")
|
|
info("#{agent_unlimited.name} has no capacity limit")
|
|
|
|
# Create 8 conversations
|
|
# Expected distribution:
|
|
# - agent_limited: 3 (hits capacity limit)
|
|
# - agent_unlimited: 5 (takes remaining conversations)
|
|
create_bulk_conversations(inbox, count: 8)
|
|
|
|
# Run assignment
|
|
assigned_count = run_assignment(inbox)
|
|
|
|
# Verify capacity limits respected
|
|
log('Verifying capacity limits...', color: :blue)
|
|
|
|
# All 8 should be assigned
|
|
all_assigned = assert_equal(
|
|
assigned_count,
|
|
8,
|
|
'All 8 conversations assigned'
|
|
)
|
|
|
|
# Agent_limited should have exactly 3 (at capacity limit)
|
|
limited_count = inbox.conversations.where(assignee: agent_limited).count
|
|
limited_at_capacity = assert_equal(
|
|
limited_count,
|
|
3,
|
|
"#{agent_limited.name} has 3 conversations (at capacity)"
|
|
)
|
|
|
|
# Agent_unlimited should have 5 (took the rest)
|
|
unlimited_count = inbox.conversations.where(assignee: agent_unlimited).count
|
|
unlimited_got_rest = assert_equal(
|
|
unlimited_count,
|
|
5,
|
|
"#{agent_unlimited.name} has 5 conversations (no limit)"
|
|
)
|
|
|
|
test1_ok = all_assigned && limited_at_capacity && unlimited_got_rest
|
|
|
|
# Test 2: More conversations arrive - only unlimited agent gets them
|
|
section('Test 2: Limited Agent at Capacity')
|
|
|
|
# Create 3 more conversations
|
|
create_bulk_conversations(inbox, count: 3)
|
|
|
|
# Run assignment
|
|
assigned_count_2 = run_assignment(inbox)
|
|
|
|
# Verify only unlimited agent gets assignments
|
|
log('Verifying only unlimited agent gets new assignments...', color: :blue)
|
|
|
|
# All 3 should be assigned
|
|
all_assigned_2 = assert_equal(
|
|
assigned_count_2,
|
|
3,
|
|
'All 3 new conversations assigned'
|
|
)
|
|
|
|
# Agent_limited still has 3 (at capacity, gets no new ones)
|
|
limited_still_count = inbox.conversations.where(assignee: agent_limited).count
|
|
limited_unchanged = assert_equal(
|
|
limited_still_count,
|
|
3,
|
|
"#{agent_limited.name} still has 3 (at capacity)"
|
|
)
|
|
|
|
# Agent_unlimited now has 8 (5 + 3)
|
|
unlimited_new_count = inbox.conversations.where(assignee: agent_unlimited).count
|
|
unlimited_got_all_new = assert_equal(
|
|
unlimited_new_count,
|
|
8,
|
|
"#{agent_unlimited.name} has 8 conversations (got all new ones)"
|
|
)
|
|
|
|
test2_ok = all_assigned_2 && limited_unchanged && unlimited_got_all_new
|
|
|
|
# Test 3: Resolve some conversations - capacity frees up
|
|
section('Test 3: Capacity Frees Up When Conversations Resolve')
|
|
|
|
# Resolve 2 of agent_limited's conversations
|
|
agent_limited_conversations = inbox.conversations.where(assignee: agent_limited).limit(2)
|
|
agent_limited_conversations.each { |conv| conv.update!(status: 'resolved') }
|
|
info("Resolved 2 of #{agent_limited.name}'s conversations")
|
|
|
|
# Create 4 more conversations
|
|
create_bulk_conversations(inbox, count: 4)
|
|
|
|
# Run assignment
|
|
assigned_count_3 = run_assignment(inbox)
|
|
|
|
# Verify agent_limited can get assignments again (up to capacity)
|
|
log('Verifying capacity freed up...', color: :blue)
|
|
|
|
# All 4 should be assigned
|
|
all_assigned_3 = assert_equal(
|
|
assigned_count_3,
|
|
4,
|
|
'All 4 final conversations assigned'
|
|
)
|
|
|
|
# Agent_limited should have 3 open conversations again (was 1, got 2 more)
|
|
limited_open_count = inbox.conversations.where(assignee: agent_limited, status: 'open').count
|
|
limited_filled_capacity = assert_equal(
|
|
limited_open_count,
|
|
3,
|
|
"#{agent_limited.name} has 3 open conversations (capacity filled again)"
|
|
)
|
|
|
|
# Agent_unlimited should have 10 open conversations (8 + 2)
|
|
unlimited_final_count = inbox.conversations.where(assignee: agent_unlimited, status: 'open').count
|
|
unlimited_got_remainder = assert_equal(
|
|
unlimited_final_count,
|
|
10,
|
|
"#{agent_unlimited.name} has 10 open conversations (got remainder)"
|
|
)
|
|
|
|
test3_ok = all_assigned_3 && limited_filled_capacity && unlimited_got_remainder
|
|
|
|
# Show final distribution (open only)
|
|
log('Final Distribution (open conversations only):', color: :blue)
|
|
puts " #{agent_limited.name}: #{limited_open_count} conversations (limit: 3)"
|
|
puts " #{agent_unlimited.name}: #{unlimited_final_count} conversations (no limit)"
|
|
|
|
# Final result
|
|
if test1_ok && test2_ok && test3_ok
|
|
section('✓ ALL TESTS PASSED')
|
|
true
|
|
else
|
|
section('✗ SOME TESTS FAILED')
|
|
false
|
|
end
|
|
rescue StandardError => e
|
|
error("Test failed with error: #{e.message}")
|
|
puts e.backtrace.first(5).join("\n")
|
|
false
|
|
ensure
|
|
cleanup_test_data(account, inbox: inbox) if inbox
|
|
end
|
|
end
|
|
end
|
|
|
|
# Run test and exit with appropriate code
|
|
exit(TestCapacityLimits.new.run ? 0 : 1)
|