Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c80ab26ad9 | ||
|
|
e523db12f4 | ||
|
|
8bacbd2b23 | ||
|
|
8aa37907c0 |
@@ -111,7 +111,7 @@ describe('useMacros', () => {
|
|||||||
useStoreGetters.mockReturnValue({
|
useStoreGetters.mockReturnValue({
|
||||||
'labels/getLabels': { value: mockLabels },
|
'labels/getLabels': { value: mockLabels },
|
||||||
'teams/getTeams': { value: mockTeams },
|
'teams/getTeams': { value: mockTeams },
|
||||||
'agents/getAgents': { value: mockAgents },
|
'agents/getVerifiedAgents': { value: mockAgents },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -119,24 +119,30 @@ describe('useMacros', () => {
|
|||||||
const { getMacroDropdownValues } = useMacros();
|
const { getMacroDropdownValues } = useMacros();
|
||||||
expect(getMacroDropdownValues('add_label')).toHaveLength(mockLabels.length);
|
expect(getMacroDropdownValues('add_label')).toHaveLength(mockLabels.length);
|
||||||
expect(getMacroDropdownValues('assign_team')).toHaveLength(
|
expect(getMacroDropdownValues('assign_team')).toHaveLength(
|
||||||
mockTeams.length
|
mockTeams.length + 1
|
||||||
);
|
); // +1 for "None"
|
||||||
expect(getMacroDropdownValues('assign_agent')).toHaveLength(
|
expect(getMacroDropdownValues('assign_agent')).toHaveLength(
|
||||||
mockAgents.length + 1
|
mockAgents.length + 2
|
||||||
); // +1 for "Self"
|
); // +2 for "None" and "Self"
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns teams for assign_team and send_email_to_team types', () => {
|
it('returns teams with "None" option for assign_team and teams only for send_email_to_team', () => {
|
||||||
const { getMacroDropdownValues } = useMacros();
|
const { getMacroDropdownValues } = useMacros();
|
||||||
expect(getMacroDropdownValues('assign_team')).toEqual(mockTeams);
|
const assignTeamResult = getMacroDropdownValues('assign_team');
|
||||||
|
expect(assignTeamResult[0]).toEqual({
|
||||||
|
id: 'nil',
|
||||||
|
name: 'AUTOMATION.NONE_OPTION',
|
||||||
|
});
|
||||||
|
expect(assignTeamResult.slice(1)).toEqual(mockTeams);
|
||||||
expect(getMacroDropdownValues('send_email_to_team')).toEqual(mockTeams);
|
expect(getMacroDropdownValues('send_email_to_team')).toEqual(mockTeams);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns agents with "Self" option for assign_agent type', () => {
|
it('returns agents with "None" and "Self" options for assign_agent type', () => {
|
||||||
const { getMacroDropdownValues } = useMacros();
|
const { getMacroDropdownValues } = useMacros();
|
||||||
const result = getMacroDropdownValues('assign_agent');
|
const result = getMacroDropdownValues('assign_agent');
|
||||||
expect(result[0]).toEqual({ id: 'self', name: 'Self' });
|
expect(result[0]).toEqual({ id: 'nil', name: 'AUTOMATION.NONE_OPTION' });
|
||||||
expect(result.slice(1)).toEqual(mockAgents);
|
expect(result[1]).toEqual({ id: 'self', name: 'Self' });
|
||||||
|
expect(result.slice(2)).toEqual(mockAgents);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns formatted labels for add_label and remove_label types', () => {
|
it('returns formatted labels for add_label and remove_label types', () => {
|
||||||
@@ -167,13 +173,16 @@ describe('useMacros', () => {
|
|||||||
useStoreGetters.mockReturnValue({
|
useStoreGetters.mockReturnValue({
|
||||||
'labels/getLabels': { value: [] },
|
'labels/getLabels': { value: [] },
|
||||||
'teams/getTeams': { value: [] },
|
'teams/getTeams': { value: [] },
|
||||||
'agents/getAgents': { value: [] },
|
'agents/getVerifiedAgents': { value: [] },
|
||||||
});
|
});
|
||||||
|
|
||||||
const { getMacroDropdownValues } = useMacros();
|
const { getMacroDropdownValues } = useMacros();
|
||||||
expect(getMacroDropdownValues('add_label')).toEqual([]);
|
expect(getMacroDropdownValues('add_label')).toEqual([]);
|
||||||
expect(getMacroDropdownValues('assign_team')).toEqual([]);
|
expect(getMacroDropdownValues('assign_team')).toEqual([
|
||||||
|
{ id: 'nil', name: 'AUTOMATION.NONE_OPTION' },
|
||||||
|
]);
|
||||||
expect(getMacroDropdownValues('assign_agent')).toEqual([
|
expect(getMacroDropdownValues('assign_agent')).toEqual([
|
||||||
|
{ id: 'nil', name: 'AUTOMATION.NONE_OPTION' },
|
||||||
{ id: 'self', name: 'Self' },
|
{ id: 'self', name: 'Self' },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,12 @@ export const useMacros = () => {
|
|||||||
|
|
||||||
const labels = computed(() => getters['labels/getLabels'].value);
|
const labels = computed(() => getters['labels/getLabels'].value);
|
||||||
const teams = computed(() => getters['teams/getTeams'].value);
|
const teams = computed(() => getters['teams/getTeams'].value);
|
||||||
const agents = computed(() => getters['agents/getAgents'].value);
|
const agents = computed(() => getters['agents/getVerifiedAgents'].value);
|
||||||
|
|
||||||
|
const withNoneOption = options => [
|
||||||
|
{ id: 'nil', name: t('AUTOMATION.NONE_OPTION') },
|
||||||
|
...(options || []),
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get dropdown values based on the specified type
|
* Get dropdown values based on the specified type
|
||||||
@@ -23,10 +28,15 @@ export const useMacros = () => {
|
|||||||
const getMacroDropdownValues = type => {
|
const getMacroDropdownValues = type => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'assign_team':
|
case 'assign_team':
|
||||||
|
return withNoneOption(teams.value);
|
||||||
case 'send_email_to_team':
|
case 'send_email_to_team':
|
||||||
return teams.value;
|
return teams.value;
|
||||||
case 'assign_agent':
|
case 'assign_agent':
|
||||||
return [{ id: 'self', name: 'Self' }, ...agents.value];
|
return [
|
||||||
|
...withNoneOption(),
|
||||||
|
{ id: 'self', name: 'Self' },
|
||||||
|
...agents.value,
|
||||||
|
];
|
||||||
case 'add_label':
|
case 'add_label':
|
||||||
case 'remove_label':
|
case 'remove_label':
|
||||||
return labels.value.map(i => ({
|
return labels.value.map(i => ({
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ describe('#resolveTeamIds', () => {
|
|||||||
const resolvedTeams = '⚙️ sales team, 🤷♂️ fayaz';
|
const resolvedTeams = '⚙️ sales team, 🤷♂️ fayaz';
|
||||||
expect(resolveTeamIds(teams, [1, 2])).toEqual(resolvedTeams);
|
expect(resolveTeamIds(teams, [1, 2])).toEqual(resolvedTeams);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('resolves nil as None', () => {
|
||||||
|
expect(resolveTeamIds(teams, ['nil'])).toEqual('None');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#resolveLabels', () => {
|
describe('#resolveLabels', () => {
|
||||||
@@ -59,6 +63,10 @@ describe('#resolveAgents', () => {
|
|||||||
const resolvedAgents = 'John Doe';
|
const resolvedAgents = 'John Doe';
|
||||||
expect(resolveAgents(agents, [1])).toEqual(resolvedAgents);
|
expect(resolveAgents(agents, [1])).toEqual(resolvedAgents);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('resolves nil and self values', () => {
|
||||||
|
expect(resolveAgents(agents, ['nil', 'self'])).toEqual('None, Self');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#getFileName', () => {
|
describe('#getFileName', () => {
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ const validateSingleAction = action => {
|
|||||||
'mute_conversation',
|
'mute_conversation',
|
||||||
'snooze_conversation',
|
'snooze_conversation',
|
||||||
'resolve_conversation',
|
'resolve_conversation',
|
||||||
|
'remove_assigned_agent',
|
||||||
'remove_assigned_team',
|
'remove_assigned_team',
|
||||||
'open_conversation',
|
'open_conversation',
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -137,6 +137,8 @@
|
|||||||
"ACTIONS": {
|
"ACTIONS": {
|
||||||
"ASSIGN_AGENT": "Assign to Agent",
|
"ASSIGN_AGENT": "Assign to Agent",
|
||||||
"ASSIGN_TEAM": "Assign a Team",
|
"ASSIGN_TEAM": "Assign a Team",
|
||||||
|
"REMOVE_ASSIGNED_AGENT": "Remove Assigned Agent",
|
||||||
|
"REMOVE_ASSIGNED_TEAM": "Remove Assigned Team",
|
||||||
"ADD_LABEL": "Add a Label",
|
"ADD_LABEL": "Add a Label",
|
||||||
"REMOVE_LABEL": "Remove a Label",
|
"REMOVE_LABEL": "Remove a Label",
|
||||||
"SEND_EMAIL_TO_TEAM": "Send an Email to Team",
|
"SEND_EMAIL_TO_TEAM": "Send an Email to Team",
|
||||||
|
|||||||
@@ -89,6 +89,7 @@
|
|||||||
"ASSIGN_AGENT": "Assign an Agent",
|
"ASSIGN_AGENT": "Assign an Agent",
|
||||||
"ADD_LABEL": "Add a Label",
|
"ADD_LABEL": "Add a Label",
|
||||||
"REMOVE_LABEL": "Remove a Label",
|
"REMOVE_LABEL": "Remove a Label",
|
||||||
|
"REMOVE_ASSIGNED_AGENT": "Remove Assigned Agent",
|
||||||
"REMOVE_ASSIGNED_TEAM": "Remove Assigned Team",
|
"REMOVE_ASSIGNED_TEAM": "Remove Assigned Team",
|
||||||
"SEND_EMAIL_TRANSCRIPT": "Send an Email Transcript",
|
"SEND_EMAIL_TRANSCRIPT": "Send an Email Transcript",
|
||||||
"MUTE_CONVERSATION": "Mute Conversation",
|
"MUTE_CONVERSATION": "Mute Conversation",
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ const getActionValue = (key, params) => {
|
|||||||
add_label: resolveLabels(labels.value, params),
|
add_label: resolveLabels(labels.value, params),
|
||||||
remove_label: resolveLabels(labels.value, params),
|
remove_label: resolveLabels(labels.value, params),
|
||||||
assign_agent: resolveAgents(agents.value, params),
|
assign_agent: resolveAgents(agents.value, params),
|
||||||
|
remove_assigned_agent: null,
|
||||||
mute_conversation: null,
|
mute_conversation: null,
|
||||||
snooze_conversation: null,
|
snooze_conversation: null,
|
||||||
resolve_conversation: null,
|
resolve_conversation: null,
|
||||||
|
|||||||
@@ -78,6 +78,14 @@ export const AUTOMATIONS = {
|
|||||||
key: 'assign_team',
|
key: 'assign_team',
|
||||||
name: 'ASSIGN_TEAM',
|
name: 'ASSIGN_TEAM',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'remove_assigned_agent',
|
||||||
|
name: 'REMOVE_ASSIGNED_AGENT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'remove_assigned_team',
|
||||||
|
name: 'REMOVE_ASSIGNED_TEAM',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'add_label',
|
key: 'add_label',
|
||||||
name: 'ADD_LABEL',
|
name: 'ADD_LABEL',
|
||||||
@@ -196,6 +204,14 @@ export const AUTOMATIONS = {
|
|||||||
key: 'assign_team',
|
key: 'assign_team',
|
||||||
name: 'ASSIGN_TEAM',
|
name: 'ASSIGN_TEAM',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'remove_assigned_agent',
|
||||||
|
name: 'REMOVE_ASSIGNED_AGENT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'remove_assigned_team',
|
||||||
|
name: 'REMOVE_ASSIGNED_TEAM',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'assign_agent',
|
key: 'assign_agent',
|
||||||
name: 'ASSIGN_AGENT',
|
name: 'ASSIGN_AGENT',
|
||||||
@@ -318,6 +334,14 @@ export const AUTOMATIONS = {
|
|||||||
key: 'assign_team',
|
key: 'assign_team',
|
||||||
name: 'ASSIGN_TEAM',
|
name: 'ASSIGN_TEAM',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'remove_assigned_agent',
|
||||||
|
name: 'REMOVE_ASSIGNED_AGENT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'remove_assigned_team',
|
||||||
|
name: 'REMOVE_ASSIGNED_TEAM',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'assign_agent',
|
key: 'assign_agent',
|
||||||
name: 'ASSIGN_AGENT',
|
name: 'ASSIGN_AGENT',
|
||||||
@@ -434,6 +458,14 @@ export const AUTOMATIONS = {
|
|||||||
key: 'assign_team',
|
key: 'assign_team',
|
||||||
name: 'ASSIGN_TEAM',
|
name: 'ASSIGN_TEAM',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'remove_assigned_agent',
|
||||||
|
name: 'REMOVE_ASSIGNED_AGENT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'remove_assigned_team',
|
||||||
|
name: 'REMOVE_ASSIGNED_TEAM',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'assign_agent',
|
key: 'assign_agent',
|
||||||
name: 'ASSIGN_AGENT',
|
name: 'ASSIGN_AGENT',
|
||||||
@@ -546,6 +578,14 @@ export const AUTOMATIONS = {
|
|||||||
key: 'assign_team',
|
key: 'assign_team',
|
||||||
name: 'ASSIGN_TEAM',
|
name: 'ASSIGN_TEAM',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'remove_assigned_agent',
|
||||||
|
name: 'REMOVE_ASSIGNED_AGENT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'remove_assigned_team',
|
||||||
|
name: 'REMOVE_ASSIGNED_TEAM',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'send_email_to_team',
|
key: 'send_email_to_team',
|
||||||
name: 'SEND_EMAIL_TO_TEAM',
|
name: 'SEND_EMAIL_TO_TEAM',
|
||||||
@@ -604,6 +644,16 @@ export const AUTOMATION_ACTION_TYPES = [
|
|||||||
label: 'ASSIGN_TEAM',
|
label: 'ASSIGN_TEAM',
|
||||||
inputType: 'search_select',
|
inputType: 'search_select',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'remove_assigned_agent',
|
||||||
|
label: 'REMOVE_ASSIGNED_AGENT',
|
||||||
|
inputType: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'remove_assigned_team',
|
||||||
|
label: 'REMOVE_ASSIGNED_TEAM',
|
||||||
|
inputType: null,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'add_label',
|
key: 'add_label',
|
||||||
label: 'ADD_LABEL',
|
label: 'ADD_LABEL',
|
||||||
|
|||||||
@@ -58,7 +58,9 @@ const formatMacro = macroData => {
|
|||||||
),
|
),
|
||||||
message: action.action_params[0].message,
|
message: action.action_params[0].message,
|
||||||
};
|
};
|
||||||
} else actionParams = [...action.action_params];
|
} else {
|
||||||
|
actionParams = [...action.action_params];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...action,
|
...action,
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ export const MACRO_ACTION_TYPES = [
|
|||||||
label: 'REMOVE_LABEL',
|
label: 'REMOVE_LABEL',
|
||||||
inputType: 'multi_select',
|
inputType: 'multi_select',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'remove_assigned_agent',
|
||||||
|
label: 'REMOVE_ASSIGNED_AGENT',
|
||||||
|
inputType: null,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'remove_assigned_team',
|
key: 'remove_assigned_team',
|
||||||
label: 'REMOVE_ASSIGNED_TEAM',
|
label: 'REMOVE_ASSIGNED_TEAM',
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export const resolveActionName = key => {
|
|||||||
export const resolveTeamIds = (teams, ids) => {
|
export const resolveTeamIds = (teams, ids) => {
|
||||||
return ids
|
return ids
|
||||||
.map(id => {
|
.map(id => {
|
||||||
|
if (id === 'nil') return 'None';
|
||||||
const team = teams.find(i => i.id === id);
|
const team = teams.find(i => i.id === id);
|
||||||
return team ? team.name : '';
|
return team ? team.name : '';
|
||||||
})
|
})
|
||||||
@@ -35,6 +36,8 @@ export const resolveLabels = (labels, ids) => {
|
|||||||
export const resolveAgents = (agents, ids) => {
|
export const resolveAgents = (agents, ids) => {
|
||||||
return ids
|
return ids
|
||||||
.map(id => {
|
.map(id => {
|
||||||
|
if (id === 'nil') return 'None';
|
||||||
|
if (id === 'self') return 'Self';
|
||||||
const agent = agents.find(i => i.id === id);
|
const agent = agents.find(i => i.id === id);
|
||||||
return agent ? agent.name : '';
|
return agent ? agent.name : '';
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -40,9 +40,9 @@ class AutomationRule < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def actions_attributes
|
def actions_attributes
|
||||||
%w[send_message add_label remove_label send_email_to_team assign_team assign_agent send_webhook_event mute_conversation
|
%w[send_message add_label remove_label send_email_to_team assign_team assign_agent remove_assigned_agent
|
||||||
send_attachment change_status resolve_conversation open_conversation snooze_conversation change_priority send_email_transcript
|
remove_assigned_team send_webhook_event mute_conversation send_attachment change_status resolve_conversation
|
||||||
add_private_note].freeze
|
open_conversation snooze_conversation change_priority send_email_transcript add_private_note].freeze
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_base_data
|
def file_base_data
|
||||||
|
|||||||
+3
-3
@@ -30,9 +30,9 @@ class Macro < ApplicationRecord
|
|||||||
|
|
||||||
validate :json_actions_format
|
validate :json_actions_format
|
||||||
|
|
||||||
ACTIONS_ATTRS = %w[send_message add_label assign_team assign_agent mute_conversation change_status remove_label remove_assigned_team
|
ACTIONS_ATTRS = %w[send_message add_label assign_team assign_agent mute_conversation change_status remove_label remove_assigned_agent
|
||||||
resolve_conversation snooze_conversation change_priority send_email_transcript send_attachment
|
remove_assigned_team resolve_conversation snooze_conversation change_priority send_email_transcript
|
||||||
add_private_note send_webhook_event].freeze
|
send_attachment add_private_note send_webhook_event].freeze
|
||||||
|
|
||||||
def set_visibility(user, params)
|
def set_visibility(user, params)
|
||||||
self.visibility = params[:visibility]
|
self.visibility = params[:visibility]
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ class ActionService
|
|||||||
@conversation.open!
|
@conversation.open!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pending_conversation(_params)
|
||||||
|
@conversation.pending!
|
||||||
|
end
|
||||||
|
|
||||||
def change_status(status)
|
def change_status(status)
|
||||||
@conversation.update!(status: status[0])
|
@conversation.update!(status: status[0])
|
||||||
end
|
end
|
||||||
@@ -43,7 +47,9 @@ class ActionService
|
|||||||
|
|
||||||
@agent = @account.users.find_by(id: agent_ids)
|
@agent = @account.users.find_by(id: agent_ids)
|
||||||
|
|
||||||
@conversation.update!(assignee_id: @agent.id) if @agent.present?
|
return unless @agent.present? && @agent.confirmed?
|
||||||
|
|
||||||
|
@conversation.update!(assignee_id: @agent.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_label(labels)
|
def remove_label(labels)
|
||||||
@@ -54,8 +60,7 @@ class ActionService
|
|||||||
end
|
end
|
||||||
|
|
||||||
def assign_team(team_ids = [])
|
def assign_team(team_ids = [])
|
||||||
# FIXME: The explicit checks for zero or nil (string) is bad. Move
|
# Keep nil/0 handling for existing automation and macro payloads.
|
||||||
# this to a separate unassign action.
|
|
||||||
should_unassign = team_ids.blank? || %w[nil 0].include?(team_ids[0].to_s)
|
should_unassign = team_ids.blank? || %w[nil 0].include?(team_ids[0].to_s)
|
||||||
return @conversation.update!(team_id: nil) if should_unassign
|
return @conversation.update!(team_id: nil) if should_unassign
|
||||||
|
|
||||||
@@ -66,16 +71,25 @@ class ActionService
|
|||||||
@conversation.update!(team_id: team_ids[0])
|
@conversation.update!(team_id: team_ids[0])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def remove_assigned_agent(_params)
|
||||||
|
@conversation.update!(assignee_id: nil)
|
||||||
|
end
|
||||||
|
|
||||||
def remove_assigned_team(_params)
|
def remove_assigned_team(_params)
|
||||||
@conversation.update!(team_id: nil)
|
@conversation.update!(team_id: nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
def send_email_transcript(emails)
|
def send_email_transcript(emails)
|
||||||
|
return unless @account.email_transcript_enabled?
|
||||||
|
|
||||||
emails = emails[0].gsub(/\s+/, '').split(',')
|
emails = emails[0].gsub(/\s+/, '').split(',')
|
||||||
|
|
||||||
emails.each do |email|
|
emails.each do |email|
|
||||||
|
break unless @account.within_email_rate_limit?
|
||||||
|
|
||||||
email = parse_email_variables(@conversation, email)
|
email = parse_email_variables(@conversation, email)
|
||||||
ConversationReplyMailer.with(account: @conversation.account).conversation_transcript(@conversation, email)&.deliver_later
|
ConversationReplyMailer.with(account: @conversation.account).conversation_transcript(@conversation, email)&.deliver_later
|
||||||
|
@account.increment_email_sent_count
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,12 @@ RSpec.describe 'Api::V1::Accounts::AutomationRulesController', type: :request do
|
|||||||
'action_name': :assign_team,
|
'action_name': :assign_team,
|
||||||
'action_params': [1]
|
'action_params': [1]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'action_name': :remove_assigned_agent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'action_name': :remove_assigned_team
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'action_name': :add_label,
|
'action_name': :add_label,
|
||||||
'action_params': %w[support priority_customer]
|
'action_params': %w[support priority_customer]
|
||||||
|
|||||||
@@ -78,6 +78,9 @@ RSpec.describe 'Api::V1::Accounts::MacrosController', type: :request do
|
|||||||
'action_name': :add_label,
|
'action_name': :add_label,
|
||||||
'action_params': %w[support priority_customer]
|
'action_params': %w[support priority_customer]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'action_name': :remove_assigned_agent
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'action_name': :remove_assigned_team
|
'action_name': :remove_assigned_team
|
||||||
},
|
},
|
||||||
@@ -410,6 +413,22 @@ RSpec.describe 'Api::V1::Accounts::MacrosController', type: :request do
|
|||||||
|
|
||||||
expect(conversation.reload.team_id).to be_nil
|
expect(conversation.reload.team_id).to be_nil
|
||||||
end
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ RSpec.describe AutomationRule do
|
|||||||
action_name: :assign_team,
|
action_name: :assign_team,
|
||||||
action_params: [1]
|
action_params: [1]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
action_name: :remove_assigned_agent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action_name: :remove_assigned_team
|
||||||
|
},
|
||||||
{
|
{
|
||||||
action_name: :add_label,
|
action_name: :add_label,
|
||||||
action_params: %w[support priority_customer]
|
action_params: %w[support priority_customer]
|
||||||
|
|||||||
@@ -50,6 +50,26 @@ describe ActionService do
|
|||||||
action_service.assign_agent(['nil'])
|
action_service.assign_agent(['nil'])
|
||||||
expect(conversation.reload.assignee).to be_nil
|
expect(conversation.reload.assignee).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when agent is confirmed' do
|
||||||
|
it 'assigns the agent to the conversation' do
|
||||||
|
inbox_member
|
||||||
|
action_service.assign_agent([agent.id])
|
||||||
|
expect(conversation.reload.assignee).to eq(agent)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when agent is unconfirmed' do
|
||||||
|
let(:unconfirmed_agent) { create(:user, account: account, role: :agent, skip_confirmation: false) }
|
||||||
|
let(:unconfirmed_inbox_member) { create(:inbox_member, inbox: conversation.inbox, user: unconfirmed_agent) }
|
||||||
|
|
||||||
|
it 'does not assign unconfirmed agent to the conversation' do
|
||||||
|
unconfirmed_inbox_member
|
||||||
|
original_assignee = conversation.assignee
|
||||||
|
action_service.assign_agent([unconfirmed_agent.id])
|
||||||
|
expect(conversation.reload.assignee).to eq(original_assignee)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#assign_team' do
|
describe '#assign_team' do
|
||||||
@@ -92,4 +112,26 @@ describe ActionService do
|
|||||||
end
|
end
|
||||||
end
|
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
|
||||||
|
|
||||||
|
describe '#remove_assigned_team' do
|
||||||
|
let(:conversation) { create(:conversation, :with_team, account: account) }
|
||||||
|
let(:action_service) { described_class.new(conversation) }
|
||||||
|
|
||||||
|
it 'unassigns the team' do
|
||||||
|
expect(conversation.reload.team).to be_present
|
||||||
|
action_service.remove_assigned_team(nil)
|
||||||
|
expect(conversation.reload.team).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -88,7 +88,35 @@ RSpec.describe AutomationRules::ActionService do
|
|||||||
end
|
end
|
||||||
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
|
describe '#perform with send_email_transcript action' do
|
||||||
|
let(:account_double) do
|
||||||
|
double(
|
||||||
|
email_transcript_enabled?: true,
|
||||||
|
within_email_rate_limit?: true,
|
||||||
|
increment_email_sent_count: true
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
rule.actions << { action_name: 'send_email_transcript', action_params: ['contact@example.com, agent@example.com,agent1@example.com'] }
|
rule.actions << { action_name: 'send_email_transcript', action_params: ['contact@example.com, agent@example.com,agent1@example.com'] }
|
||||||
rule.save
|
rule.save
|
||||||
@@ -101,7 +129,7 @@ RSpec.describe AutomationRules::ActionService do
|
|||||||
allow(mailer).to receive(:conversation_transcript).with(conversation, 'agent@example.com')
|
allow(mailer).to receive(:conversation_transcript).with(conversation, 'agent@example.com')
|
||||||
allow(mailer).to receive(:conversation_transcript).with(conversation, 'agent1@example.com')
|
allow(mailer).to receive(:conversation_transcript).with(conversation, 'agent1@example.com')
|
||||||
|
|
||||||
described_class.new(rule, account, conversation).perform
|
described_class.new(rule, account_double, conversation).perform
|
||||||
expect(mailer).to have_received(:conversation_transcript).exactly(3).times
|
expect(mailer).to have_received(:conversation_transcript).exactly(3).times
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -113,7 +141,7 @@ RSpec.describe AutomationRules::ActionService do
|
|||||||
allow(ConversationReplyMailer).to receive(:with).and_return(mailer)
|
allow(ConversationReplyMailer).to receive(:with).and_return(mailer)
|
||||||
allow(mailer).to receive(:conversation_transcript).with(conversation, conversation.contact.email)
|
allow(mailer).to receive(:conversation_transcript).with(conversation, conversation.contact.email)
|
||||||
|
|
||||||
described_class.new(rule.reload, account, conversation).perform
|
described_class.new(rule.reload, account_double, conversation).perform
|
||||||
expect(mailer).to have_received(:conversation_transcript).exactly(1).times
|
expect(mailer).to have_received(:conversation_transcript).exactly(1).times
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -49,6 +49,19 @@ RSpec.describe Macros::ExecutionService, type: :service do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#assign_team' do
|
||||||
|
let(:team) { create(:team, account: account) }
|
||||||
|
|
||||||
|
context 'when team_id is nil' do
|
||||||
|
it 'unassigns the team from the conversation' do
|
||||||
|
# Directly set the team_id to avoid auto-assignment logic
|
||||||
|
conversation.update_column(:team_id, team.id)
|
||||||
|
service.send(:assign_team, ['nil'])
|
||||||
|
expect(conversation.reload.team).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#assign_agent' do
|
describe '#assign_agent' do
|
||||||
context 'when agent_ids contains self' do
|
context 'when agent_ids contains self' do
|
||||||
it 'updates the conversation assignee to the current user' do
|
it 'updates the conversation assignee to the current user' do
|
||||||
@@ -69,6 +82,14 @@ RSpec.describe Macros::ExecutionService, type: :service do
|
|||||||
expect(conversation.reload.assignee).to eq(other_user)
|
expect(conversation.reload.assignee).to eq(other_user)
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
||||||
describe '#add_private_note' do
|
describe '#add_private_note' do
|
||||||
|
|||||||
Reference in New Issue
Block a user