From aa903a5da98651bc45e6852f5b16bbc99ae24f13 Mon Sep 17 00:00:00 2001 From: Tejaswini Chile Date: Mon, 13 Jun 2022 11:58:54 +0530 Subject: [PATCH] Fix: backend changes for custom attribute (#4830) --- .../accounts/automation_rules_controller.rb | 2 +- .../components/widgets/FilterInput/Index.vue | 26 +++++ .../conditions_filter_service.rb | 4 +- app/services/contacts/filter_service.rb | 2 +- app/services/conversations/filter_service.rb | 2 +- app/services/filter_service.rb | 26 +++-- .../automation_rules_controller_spec.rb | 104 +++++++++--------- .../automation_rule_listener_spec.rb | 25 +++++ 8 files changed, 122 insertions(+), 69 deletions(-) diff --git a/app/controllers/api/v1/accounts/automation_rules_controller.rb b/app/controllers/api/v1/accounts/automation_rules_controller.rb index 78cd15e31..859c8a4bf 100644 --- a/app/controllers/api/v1/accounts/automation_rules_controller.rb +++ b/app/controllers/api/v1/accounts/automation_rules_controller.rb @@ -76,7 +76,7 @@ class Api::V1::Accounts::AutomationRulesController < Api::V1::Accounts::BaseCont def automation_rules_permit params.permit( :name, :description, :event_name, :account_id, :active, - conditions: [:attribute_key, :filter_operator, :query_operator, { values: [] }], + conditions: [:attribute_key, :filter_operator, :query_operator, :custom_attribute_type, { values: [] }], actions: [:action_name, { action_params: [] }] ) end diff --git a/app/javascript/dashboard/components/widgets/FilterInput/Index.vue b/app/javascript/dashboard/components/widgets/FilterInput/Index.vue index 25203642a..46c64fc53 100644 --- a/app/javascript/dashboard/components/widgets/FilterInput/Index.vue +++ b/app/javascript/dashboard/components/widgets/FilterInput/Index.vue @@ -215,6 +215,32 @@ export default { this.$emit('input', { ...payload, query_operator: value }); }, }, + custom_attribute_type: { + get() { + if (!this.customAttributeType) return ''; + return this.customAttributeType; + }, + set() { + const payload = this.value || {}; + this.$emit('input', { + ...payload, + custom_attribute_type: this.customAttributeType, + }); + }, + }, + }, + watch: { + customAttributeType: { + handler(value) { + if ( + value === 'conversation_attribute' || + value === 'contact_attribute' + ) { + this.value.custom_attribute_type = this.customAttributeType; + } else this.value.custom_attribute_type = ''; + }, + immediate: true, + }, }, methods: { removeFilter() { diff --git a/app/services/automation_rules/conditions_filter_service.rb b/app/services/automation_rules/conditions_filter_service.rb index e32a95751..eb351efbe 100644 --- a/app/services/automation_rules/conditions_filter_service.rb +++ b/app/services/automation_rules/conditions_filter_service.rb @@ -43,9 +43,9 @@ class AutomationRules::ConditionsFilterService < FilterService @query_string += contact_query_string(contact_filter, query_hash.with_indifferent_access, current_index) elsif message_filter @query_string += message_query_string(message_filter, query_hash.with_indifferent_access, current_index) - elsif custom_attribute(query_hash['attribute_key'], @account) + elsif custom_attribute(query_hash['attribute_key'], @account, query_hash['custom_attribute_type']) # send table name according to attribute key right now we are supporting contact based custom attribute filter - @query_string += custom_attribute_query(query_hash.with_indifferent_access, 'contacts', current_index) + @query_string += custom_attribute_query(query_hash.with_indifferent_access, query_hash['custom_attribute_type'], current_index) end end diff --git a/app/services/contacts/filter_service.rb b/app/services/contacts/filter_service.rb index 22ed9891b..aedeb172b 100644 --- a/app/services/contacts/filter_service.rb +++ b/app/services/contacts/filter_service.rb @@ -26,7 +26,7 @@ class Contacts::FilterService < FilterService query_operator = query_hash[:query_operator] filter_operator_value = filter_operation(query_hash, current_index) - return custom_attribute_query(query_hash, 'contacts', current_index) if current_filter.nil? + return custom_attribute_query(query_hash, 'contact_attribute', current_index) if current_filter.nil? case current_filter['attribute_type'] when 'additional_attributes' diff --git a/app/services/conversations/filter_service.rb b/app/services/conversations/filter_service.rb index e52fd279d..d91916b12 100644 --- a/app/services/conversations/filter_service.rb +++ b/app/services/conversations/filter_service.rb @@ -32,7 +32,7 @@ class Conversations::FilterService < FilterService query_operator = query_hash[:query_operator] filter_operator_value = filter_operation(query_hash, current_index) - return custom_attribute_query(query_hash, 'conversations', current_index) if current_filter.nil? + return custom_attribute_query(query_hash, 'conversation_attribute', current_index) if current_filter.nil? case current_filter['attribute_type'] when 'additional_attributes' diff --git a/app/services/filter_service.rb b/app/services/filter_service.rb index 0031d828d..4d17356aa 100644 --- a/app/services/filter_service.rb +++ b/app/services/filter_service.rb @@ -58,14 +58,14 @@ class FilterService end def string_filter_values(query_hash) - return query_hash['values'][0] if query_hash['values'].is_a?(Array) + return query_hash['values'][0].downcase if query_hash['values'].is_a?(Array) - query_hash['values'] + query_hash['values'].downcase end def lt_gt_filter_values(query_hash) attribute_key = query_hash[:attribute_key] - attribute_type = custom_attribute(attribute_key).try(:attribute_display_type) + attribute_type = custom_attribute(attribute_key, @account, query_hash['custom_attribute_type']).try(:attribute_display_type) attribute_data_type = self.class::ATTRIBUTE_TYPES[attribute_type] value = query_hash['values'][0] operator = query_hash['filter_operator'] == 'is_less_than' ? '<' : '>' @@ -87,27 +87,29 @@ class FilterService ] end - def custom_attribute_query(query_hash, table_name, current_index) + def custom_attribute_query(query_hash, custom_attribute_type, current_index) attribute_key = query_hash[:attribute_key] query_operator = query_hash[:query_operator] + attribute_model = custom_attribute_type || self.class::ATTRIBUTE_MODEL - attribute_type = custom_attribute(attribute_key, @account).try(:attribute_display_type) + attribute_type = custom_attribute(attribute_key, @account, attribute_model).try(:attribute_display_type) filter_operator_value = filter_operation(query_hash, current_index) attribute_data_type = self.class::ATTRIBUTE_TYPES[attribute_type] - if custom_attribute(attribute_key, @account) - " LOWER(#{table_name}.custom_attributes ->> '#{attribute_key}')::#{attribute_data_type} #{filter_operator_value} #{query_operator} " - else - ' ' - end + return ' ' if @custom_attribute.blank? + + table_name = attribute_model == 'conversation_attribute' ? 'conversations' : 'contacts' + + " LOWER(#{table_name}.custom_attributes ->> '#{attribute_key}')::#{attribute_data_type} #{filter_operator_value} #{query_operator} " end private - def custom_attribute(attribute_key, account = nil) + def custom_attribute(attribute_key, account, custom_attribute_type) current_account = account || Current.account + attribute_model = custom_attribute_type || self.class::ATTRIBUTE_MODEL @custom_attribute = current_account.custom_attribute_definitions.where( - attribute_model: self.class::ATTRIBUTE_MODEL + attribute_model: attribute_model ).find_by(attribute_key: attribute_key) end diff --git a/spec/controllers/api/v1/accounts/automation_rules_controller_spec.rb b/spec/controllers/api/v1/accounts/automation_rules_controller_spec.rb index 4513773bc..06620f7a5 100644 --- a/spec/controllers/api/v1/accounts/automation_rules_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/automation_rules_controller_spec.rb @@ -42,55 +42,55 @@ RSpec.describe 'Api::V1::Accounts::AutomationRulesController', type: :request do context 'when it is an authenticated user' do let(:params) do { - name: 'Notify Conversation Created and mark priority query', - description: 'Notify all administrator about conversation created and mark priority query', - event_name: 'conversation_created', - conditions: [ + 'name': 'Notify Conversation Created and mark priority query', + 'description': 'Notify all administrator about conversation created and mark priority query', + 'event_name': 'conversation_created', + 'conditions': [ { - attribute_key: 'browser_language', - filter_operator: 'equal_to', - values: ['en'], - query_operator: 'AND' + 'attribute_key': 'browser_language', + 'filter_operator': 'equal_to', + 'values': ['en'], + 'query_operator': 'AND' }, { - attribute_key: 'country_code', - filter_operator: 'equal_to', - values: %w[USA UK], - query_operator: nil + 'attribute_key': 'country_code', + 'filter_operator': 'equal_to', + 'values': %w[USA UK], + 'query_operator': nil } ], - actions: [ + 'actions': [ { - action_name: :send_message, - action_params: ['Welcome to the chatwoot platform.'] + 'action_name': :send_message, + 'action_params': ['Welcome to the chatwoot platform.'] }, { - action_name: :assign_team, - action_params: [1] + 'action_name': :assign_team, + 'action_params': [1] }, { - action_name: :add_label, - action_params: %w[support priority_customer] + 'action_name': :add_label, + 'action_params': %w[support priority_customer] }, { - action_name: :assign_best_administrator, - action_params: [1] + 'action_name': :assign_best_administrator, + 'action_params': [1] }, { - action_name: :update_additional_attributes, - action_params: [{ intiated_at: '2021-12-03 17:25:26.844536 +0530' }] + 'action_name': :update_additional_attributes, + 'action_params': [{ intiated_at: '2021-12-03 17:25:26.844536 +0530' }] } ] - }.with_indifferent_access + } end it 'throws an error for unknown attributes in condtions' do expect(account.automation_rules.count).to eq(0) params[:conditions] << { - attribute_key: 'unknown_attribute', - filter_operator: 'equal_to', - values: ['en'], - query_operator: 'AND' + 'attribute_key': 'unknown_attribute', + 'filter_operator': 'equal_to', + 'values': ['en'], + 'query_operator': 'AND' } post "/api/v1/accounts/#{account.id}/automation_rules", @@ -115,11 +115,11 @@ RSpec.describe 'Api::V1::Accounts::AutomationRulesController', type: :request do it 'Saves for automation_rules for account with status conditions' do params[:conditions] = [ { - attribute_key: 'status', - filter_operator: 'equal_to', - values: ['resolved'], - query_operator: nil - }.with_indifferent_access + 'attribute_key': 'status', + 'filter_operator': 'equal_to', + 'values': ['resolved'], + 'query_operator': nil + } ] expect(account.automation_rules.count).to eq(0) @@ -149,12 +149,12 @@ RSpec.describe 'Api::V1::Accounts::AutomationRulesController', type: :request do params[:actions] = [ { - action_name: :send_message, - action_params: ['Welcome to the chatwoot platform.'] + 'action_name': :send_message, + 'action_params': ['Welcome to the chatwoot platform.'] }, { - action_name: :send_attachment, - action_params: [blob['blob_id']] + 'action_name': :send_attachment, + 'action_params': [blob['blob_id']] } ] @@ -185,12 +185,12 @@ RSpec.describe 'Api::V1::Accounts::AutomationRulesController', type: :request do params[:actions] = [ { - action_name: :send_attachment, - action_params: [blob_1['blob_id']] + 'action_name': :send_attachment, + 'action_params': [blob_1['blob_id']] }, { - action_name: :send_attachment, - action_params: [blob_2['blob_id']] + 'action_name': :send_attachment, + 'action_params': [blob_2['blob_id']] } ] @@ -271,23 +271,23 @@ RSpec.describe 'Api::V1::Accounts::AutomationRulesController', type: :request do context 'when it is an authenticated user' do let(:update_params) do { - description: 'Update description', - name: 'Update name', - conditions: [ + 'description': 'Update description', + 'name': 'Update name', + 'conditions': [ { - attribute_key: 'browser_language', - filter_operator: 'equal_to', - values: ['en'], - query_operator: 'AND' + 'attribute_key': 'browser_language', + 'filter_operator': 'equal_to', + 'values': ['en'], + 'query_operator': 'AND' } ], - actions: [ + 'actions': [ { - action_name: :update_additional_attributes, - action_params: [{ intiated_at: '2021-12-03 17:25:26.844536 +0530' }] + 'action_name': :update_additional_attributes, + 'action_params': [{ intiated_at: '2021-12-03 17:25:26.844536 +0530' }] } ] - }.with_indifferent_access + } end it 'returns for cloned automation_rule for account' do diff --git a/spec/listeners/automation_rule_listener_spec.rb b/spec/listeners/automation_rule_listener_spec.rb index 8f4213137..ee13a01ba 100644 --- a/spec/listeners/automation_rule_listener_spec.rb +++ b/spec/listeners/automation_rule_listener_spec.rb @@ -356,6 +356,31 @@ describe AutomationRuleListener do end end + describe '#message_created event based on case in-sensitive filter' do + before do + automation_rule.update!( + event_name: 'message_created', + name: 'Call actions message created based on case in-sensitive filter', + description: 'Add labels, assign team after message created', + conditions: [{ 'values': ['KYC'], 'attribute_key': 'content', 'query_operator': nil, 'filter_operator': 'contains' }] + ) + end + + let!(:message) { create(:message, account: account, conversation: conversation, message_type: 'incoming', content: 'kyc message') } + let!(:event) do + Events::Base.new('message_created', Time.zone.now, { conversation: conversation, message: message }) + end + + it 'triggers automation rule based on case in-sensitive filter' do + expect(conversation.labels).to eq([]) + expect(TeamNotifications::AutomationNotificationMailer).to receive(:conversation_creation) + listener.message_created(event) + conversation.reload + + expect(conversation.labels.pluck(:name)).to contain_exactly('support', 'priority_customer') + end + end + describe '#message_created' do before do automation_rule.update!(