Feat: Automations Actions (#3564)
This commit is contained in:
parent
905fd62974
commit
7df68c6388
13 changed files with 124 additions and 7 deletions
|
@ -2,7 +2,7 @@ class Api::V1::Accounts::AutomationRulesController < Api::V1::Accounts::BaseCont
|
|||
before_action :check_authorization
|
||||
|
||||
def index
|
||||
@automation_rules = Current.account.automation_rules
|
||||
@automation_rules = Current.account.automation_rules.active
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
|
@ -14,12 +14,25 @@ class AutomationRuleListener < BaseListener
|
|||
return unless rule_present?('conversation_created', conversation)
|
||||
|
||||
@rules.each do |rule|
|
||||
conditions_match = AutomationRule::ConditionsFilterService.new(rule, conversation).perform
|
||||
AutomationRule::ActionService.new(rule, conversation).perform if conditions_match.present?
|
||||
conditions_match = ::AutomationRule::ConditionsFilterService.new(rule, conversation).perform
|
||||
::AutomationRules::ActionService.new(rule, conversation).perform if conditions_match.present?
|
||||
end
|
||||
end
|
||||
|
||||
def message_created(event_obj)
|
||||
conversation = event_obj.data[:conversation]
|
||||
message = event_obj.data[:message]
|
||||
return unless rule_present?('message_created', conversation)
|
||||
|
||||
@rules.each do |rule|
|
||||
conditions_match = ::AutomationRules::ConditionsFilterService.new(rule, conversation).message_conditions(message)
|
||||
::AutomationRules::ActionService.new(rule, conversation).perform if conditions_match.present?
|
||||
end
|
||||
end
|
||||
|
||||
def rule_present?(event_name, conversation)
|
||||
return if conversation.blank?
|
||||
|
||||
@rules = AutomationRule.where(
|
||||
event_name: event_name,
|
||||
account_id: conversation.account_id
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#
|
||||
# id :bigint not null, primary key
|
||||
# actions :jsonb not null
|
||||
# active :boolean default(TRUE), not null
|
||||
# conditions :jsonb not null
|
||||
# description :text
|
||||
# event_name :string not null
|
||||
|
@ -23,6 +24,8 @@ class AutomationRule < ApplicationRecord
|
|||
validate :json_conditions_format
|
||||
validate :json_actions_format
|
||||
|
||||
scope :active, -> { where(active: true) }
|
||||
|
||||
CONDITIONS_ATTRS = %w[country_code status browser_language assignee_id team_id referer].freeze
|
||||
ACTIONS_ATTRS = %w[send_message add_label send_email_to_team assign_team assign_best_agents].freeze
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@ class AutomationRules::ActionService
|
|||
TeamNotifications::AutomationNotificationMailer.conversation_creation(@conversation, team, params[:message])
|
||||
when 'conversation_updated'
|
||||
TeamNotifications::AutomationNotificationMailer.conversation_updated(@conversation, team, params[:message])
|
||||
when 'message_created'
|
||||
TeamNotifications::AutomationNotificationMailer.message_created(@conversation, team, params[:message])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -21,6 +21,29 @@ class AutomationRules::ConditionsFilterService < FilterService
|
|||
records.any?
|
||||
end
|
||||
|
||||
def message_conditions(_message)
|
||||
message_filters = @filters['messages']
|
||||
|
||||
@rule.conditions.each_with_index do |query_hash, current_index|
|
||||
current_filter = message_filters[query_hash['attribute_key']]
|
||||
@query_string += message_query_string(current_filter, query_hash.with_indifferent_access, current_index)
|
||||
end
|
||||
records = Message.where(conversation: @conversation).where(@query_string, @filter_values.with_indifferent_access)
|
||||
records.any?
|
||||
end
|
||||
|
||||
def message_query_string(current_filter, query_hash, current_index)
|
||||
attribute_key = query_hash['attribute_key']
|
||||
query_operator = query_hash['query_operator']
|
||||
|
||||
filter_operator_value = filter_operation(query_hash, current_index)
|
||||
|
||||
case current_filter['attribute_type']
|
||||
when 'standard'
|
||||
" messages.#{attribute_key} #{filter_operator_value} #{query_operator} "
|
||||
end
|
||||
end
|
||||
|
||||
def conversation_query_string(current_filter, query_hash, current_index)
|
||||
attribute_key = query_hash['attribute_key']
|
||||
query_operator = query_hash['query_operator']
|
||||
|
|
|
@ -31,10 +31,13 @@ class FilterService
|
|||
end
|
||||
|
||||
def filter_values(query_hash)
|
||||
if query_hash['attribute_key'] == 'status'
|
||||
case query_hash['attribute_key']
|
||||
when 'status'
|
||||
return Conversation.statuses.values if query_hash['values'].include?('all')
|
||||
|
||||
query_hash['values'].map { |x| Conversation.statuses[x.to_sym] }
|
||||
when 'message_type'
|
||||
query_hash['values'].map { |x| Message.message_types[x.to_sym] }
|
||||
else
|
||||
query_hash['values']
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
json.data do
|
||||
json.payload do
|
||||
json.array! @automation_rules do |automation_rule|
|
||||
json.partial! 'api/v1/accounts/automation_rules/partials/automation_rule.json.jbuilder', automation_rule: automation_rule
|
||||
end
|
||||
|
|
|
@ -5,3 +5,5 @@ json.description automation_rule.description
|
|||
json.event_name automation_rule.event_name
|
||||
json.conditions automation_rule.conditions
|
||||
json.actions automation_rule.actions
|
||||
json.created_on automation_rule.created_at
|
||||
json.active automation_rule.active?
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
class AddActiveFlagToAutomationRule < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
add_column :automation_rules, :active, :boolean, default: true, null: false
|
||||
end
|
||||
end
|
|
@ -133,6 +133,7 @@ ActiveRecord::Schema.define(version: 2022_01_11_223630) do
|
|||
t.jsonb "actions", default: "{}", null: false
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.boolean "active", default: true, null: false
|
||||
t.index ["account_id"], name: "index_automation_rules_on_account_id"
|
||||
end
|
||||
|
||||
|
|
|
@ -135,5 +135,21 @@
|
|||
"filter_operators": ["exactly_equal_to", "contains", "does_not_contain" ],
|
||||
"attribute_type": "standard"
|
||||
}
|
||||
},
|
||||
"messages": {
|
||||
"message_type": {
|
||||
"attribute_name": "Message Type",
|
||||
"input_type": "search_box with name tags/plain text",
|
||||
"data_type": "text",
|
||||
"filter_operators": [ "equal_to", "not_equal_to" ],
|
||||
"attribute_type": "standard"
|
||||
},
|
||||
"content": {
|
||||
"attribute_name": "Message Type",
|
||||
"input_type": "search_box with name tags/plain text",
|
||||
"data_type": "text",
|
||||
"filter_operators": [ "equal_to", "not_equal_to", "contains", "does_not_contain" ],
|
||||
"attribute_type": "standard"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ RSpec.describe 'Api::V1::Accounts::AutomationRulesController', type: :request do
|
|||
|
||||
expect(response).to have_http_status(:success)
|
||||
body = JSON.parse(response.body, symbolize_names: true)
|
||||
expect(body[:data].first[:id]).to eq(automation_rule.id)
|
||||
expect(body[:payload].first[:id]).to eq(automation_rule.id)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
require 'rails_helper'
|
||||
describe AutomationRuleListener do
|
||||
let(:listener) { described_class.instance }
|
||||
let(:account) { create(:account) }
|
||||
let!(:account) { create(:account) }
|
||||
let(:inbox) { create(:inbox, account: account) }
|
||||
let(:contact) { create(:contact, account: account, identifier: '123') }
|
||||
let(:contact_inbox) { create(:contact_inbox, contact: contact, inbox: inbox) }
|
||||
|
@ -69,4 +69,53 @@ describe AutomationRuleListener do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#message_created' do
|
||||
before do
|
||||
automation_rule.update!(
|
||||
event_name: 'message_created',
|
||||
name: 'Call actions message created',
|
||||
description: 'Add labels, assign team after message created',
|
||||
conditions: [{ 'values': ['incoming'], 'attribute_key': 'message_type', 'query_operator': nil, 'filter_operator': 'equal_to' }]
|
||||
)
|
||||
end
|
||||
|
||||
let!(:message) { create(:message, account: account, conversation: conversation, message_type: 'incoming') }
|
||||
let!(:event) do
|
||||
Events::Base.new('message_created', Time.zone.now, { conversation: conversation, message: message })
|
||||
end
|
||||
|
||||
context 'when rule matches' do
|
||||
it 'triggers automation rule to assign team' do
|
||||
expect(conversation.team_id).not_to eq(team.id)
|
||||
|
||||
automation_rule
|
||||
listener.message_created(event)
|
||||
|
||||
conversation.reload
|
||||
expect(conversation.team_id).to eq(team.id)
|
||||
end
|
||||
|
||||
it 'triggers automation rule to add label' do
|
||||
expect(conversation.labels).to eq([])
|
||||
|
||||
automation_rule
|
||||
listener.message_created(event)
|
||||
|
||||
conversation.reload
|
||||
expect(conversation.labels.pluck(:name)).to eq(%w[support priority_customer])
|
||||
end
|
||||
|
||||
it 'triggers automation rule to assign best agents' do
|
||||
expect(conversation.assignee).to be_nil
|
||||
|
||||
automation_rule
|
||||
listener.message_created(event)
|
||||
|
||||
conversation.reload
|
||||
|
||||
expect(conversation.assignee).to eq(user_1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue