fix: add explicit remove assignment actions to macros and automations (#12172)

This updates macros and automations so agents can explicitly remove
assigned agents or teams, while keeping the existing `Assign -> None`
flow working for backward compatibility.

Fixes: #7551
Closes: #7551

## Why
The original macro change exposed unassignment only through `Assign ->
None`, which made macros behave differently from automations and left
the explicit remove actions inconsistent across the product. This keeps
the lower-risk compatibility path and adds the explicit remove actions
requested in review.

## What this change does
- Adds `Remove Assigned Agent` and `Remove Assigned Team` as explicit
actions in macros.
- Adds the same explicit remove actions in automations.
- Keeps `Assign Agent -> None` and `Assign Team -> None` working for
existing behavior and stored payloads.
- Preserves backward compatibility for existing macro and automation
execution payloads.
- Downmerges the latest `develop` and resolves the conflicts while
keeping both the new remove actions and current `develop` behavior.

## Validation
- Verified both remove actions are available and selectable in the macro
editor.
- Verified both remove actions are available and selectable in the
automation builder.
- Applied a disposable macro with `Remove Assigned Agent` and `Remove
Assigned Team` on a real conversation and confirmed both fields were
cleared.
- Applied a disposable macro with `Assign Agent -> None` and `Assign
Team -> None` on a real conversation and confirmed both fields were
still cleared.
This commit is contained in:
Sojan Jose
2026-04-16 15:57:41 +05:30
committed by GitHub
parent 72b8a31f2d
commit aee979ee0b
19 changed files with 198 additions and 19 deletions

View File

@@ -68,6 +68,12 @@ RSpec.describe 'Api::V1::Accounts::AutomationRulesController', type: :request do
'action_name': :assign_team,
'action_params': [1]
},
{
'action_name': :remove_assigned_agent
},
{
'action_name': :remove_assigned_team
},
{
'action_name': :add_label,
'action_params': %w[support priority_customer]

View File

@@ -78,6 +78,9 @@ RSpec.describe 'Api::V1::Accounts::MacrosController', type: :request do
'action_name': :add_label,
'action_params': %w[support priority_customer]
},
{
'action_name': :remove_assigned_agent
},
{
'action_name': :remove_assigned_team
},
@@ -484,6 +487,22 @@ RSpec.describe 'Api::V1::Accounts::MacrosController', type: :request do
expect(conversation.reload.team_id).to be_nil
end
it 'Unassign the agent' do
macro.update!(actions: [
{ 'action_name' => 'remove_assigned_agent' }
])
conversation.update!(assignee: user_1)
expect(conversation.reload.assignee).to be_present
perform_enqueued_jobs do
post "/api/v1/accounts/#{account.id}/macros/#{macro.id}/execute",
params: { conversation_ids: [conversation.display_id] },
headers: administrator.create_new_auth_token
end
expect(conversation.reload.assignee).to be_nil
end
end
end
end

View File

@@ -37,6 +37,12 @@ RSpec.describe AutomationRule do
action_name: :assign_team,
action_params: [1]
},
{
action_name: :remove_assigned_agent
},
{
action_name: :remove_assigned_team
},
{
action_name: :add_label,
action_params: %w[support priority_customer]

View File

@@ -112,4 +112,15 @@ describe ActionService do
end
end
end
describe '#remove_assigned_agent' do
let(:conversation) { create(:conversation, :with_assignee, account: account) }
let(:action_service) { described_class.new(conversation) }
it 'unassigns the conversation' do
expect(conversation.reload.assignee).to be_present
action_service.remove_assigned_agent(nil)
expect(conversation.reload.assignee).to be_nil
end
end
end

View File

@@ -88,8 +88,31 @@ RSpec.describe AutomationRules::ActionService do
end
end
describe '#perform with remove assignment actions' do
let!(:team) { create(:team, account: account) }
before do
conversation.update!(assignee: agent, team: team)
rule.actions = [
{ action_name: 'remove_assigned_agent', action_params: [] },
{ action_name: 'remove_assigned_team', action_params: [] }
]
rule.save!
end
it 'removes assignee and team from the conversation' do
described_class.new(rule, account, conversation).perform
expect(conversation.reload.assignee).to be_nil
expect(conversation.team).to be_nil
end
end
describe '#perform with send_email_transcript action' do
before do
allow(account).to receive(:email_transcript_enabled?).and_return(true)
allow(account).to receive(:within_email_rate_limit?).and_return(true)
allow(account).to receive(:increment_email_sent_count).and_return(true)
rule.actions << { action_name: 'send_email_transcript', action_params: ['contact@example.com, agent@example.com,agent1@example.com'] }
rule.save
end

View File

@@ -49,6 +49,18 @@ RSpec.describe Macros::ExecutionService, type: :service do
end
end
describe '#assign_team' do
let(:team) { create(:team, account: account, allow_auto_assign: false) }
context 'when team_id is nil' do
it 'unassigns the team from the conversation' do
conversation.update!(team_id: team.id)
service.send(:assign_team, ['nil'])
expect(conversation.reload.team).to be_nil
end
end
end
describe '#assign_agent' do
context 'when agent_ids contains self' do
it 'updates the conversation assignee to the current user' do
@@ -69,6 +81,14 @@ RSpec.describe Macros::ExecutionService, type: :service do
expect(conversation.reload.assignee).to eq(other_user)
end
end
context 'when agent_ids contains nil' do
it 'unassigns the conversation' do
conversation.update!(assignee: user)
service.send(:assign_agent, ['nil'])
expect(conversation.reload.assignee).to be_nil
end
end
end
describe '#add_private_note' do