Feat: Automations Actions (#3564)

This commit is contained in:
Tejaswini Chile 2022-01-13 11:21:06 +05:30 committed by GitHub
parent 905fd62974
commit 7df68c6388
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 124 additions and 7 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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']

View file

@ -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

View file

@ -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

View file

@ -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?

View file

@ -0,0 +1,5 @@
class AddActiveFlagToAutomationRule < ActiveRecord::Migration[6.1]
def change
add_column :automation_rules, :active, :boolean, default: true, null: false
end
end

View file

@ -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

View file

@ -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"
}
}
}

View file

@ -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

View file

@ -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