From a7987d4d1cdf26a6913d2f123aafb83227037964 Mon Sep 17 00:00:00 2001 From: Tejaswini Chile Date: Fri, 4 Feb 2022 13:14:20 +0530 Subject: [PATCH] feat: Add date custom filter (#3892) --- app/services/contacts/filter_service.rb | 2 + app/services/conversations/filter_service.rb | 2 + app/services/filter_service.rb | 9 ++ lib/filters/filter_keys.json | 28 ++++ spec/services/contacts/filter_service_spec.rb | 78 ++++++++++ .../conversations/filter_service_spec.rb | 137 ++++++++++++++++-- 6 files changed, 247 insertions(+), 9 deletions(-) diff --git a/app/services/contacts/filter_service.rb b/app/services/contacts/filter_service.rb index aaa7412d4..81946435e 100644 --- a/app/services/contacts/filter_service.rb +++ b/app/services/contacts/filter_service.rb @@ -31,6 +31,8 @@ class Contacts::FilterService < FilterService case current_filter['attribute_type'] when 'additional_attributes' " LOWER(contacts.additional_attributes ->> '#{attribute_key}') #{filter_operator_value} #{query_operator} " + when 'date_attributes' + " (contacts.#{attribute_key})::#{current_filter['data_type']} #{filter_operator_value}#{current_filter['data_type']} #{query_operator} " when 'standard' if attribute_key == 'labels' " tags.id #{filter_operator_value} #{query_operator} " diff --git a/app/services/conversations/filter_service.rb b/app/services/conversations/filter_service.rb index 6e73ae9b8..a5773a228 100644 --- a/app/services/conversations/filter_service.rb +++ b/app/services/conversations/filter_service.rb @@ -37,6 +37,8 @@ class Conversations::FilterService < FilterService case current_filter['attribute_type'] when 'additional_attributes' " conversations.additional_attributes ->> '#{attribute_key}' #{filter_operator_value} #{query_operator} " + when 'date_attributes' + " (conversations.#{attribute_key})::#{current_filter['data_type']} #{filter_operator_value}#{current_filter['data_type']} #{query_operator} " when 'standard' if attribute_key == 'labels' " tags.name #{filter_operator_value} #{query_operator} " diff --git a/app/services/filter_service.rb b/app/services/filter_service.rb index a08fb947a..bf2d7d6a0 100644 --- a/app/services/filter_service.rb +++ b/app/services/filter_service.rb @@ -36,6 +36,8 @@ class FilterService @filter_values["value_#{current_index}"] = 'IS NULL' when 'is_greater_than', 'is_less_than' @filter_values["value_#{current_index}"] = lt_gt_filter_values(query_hash) + when 'days_before' + @filter_values["value_#{current_index}"] = days_before_filter_values(query_hash) else @filter_values["value_#{current_index}"] = filter_values(query_hash).to_s "= :value_#{current_index}" @@ -64,6 +66,13 @@ class FilterService "#{operator} '#{value}'::#{attribute_data_type}" end + def days_before_filter_values(query_hash) + date = Time.zone.today - query_hash['values'][0].to_i.days + query_hash['values'] = [date.strftime] + query_hash['filter_operator'] = 'is_less_than' + lt_gt_filter_values(query_hash) + end + def set_count_for_all_conversations [ @conversations.assigned_to(@user).count, diff --git a/lib/filters/filter_keys.json b/lib/filters/filter_keys.json index 2aa5fdab1..2736473b7 100644 --- a/lib/filters/filter_keys.json +++ b/lib/filters/filter_keys.json @@ -76,6 +76,20 @@ "data_type": "link", "filter_operators": [ "equal_to", "not_equal_to", "contains", "does_not_contain", "present", "is_not_present" ], "attribute_type": "additional_attributes" + }, + "created_at": { + "attribute_name": "Created At", + "input_type": "date", + "data_type": "date", + "filter_operators": [ "is_greater_than", "is_less_than", "days_before" ], + "attribute_type": "date_attributes" + }, + "last_activity_at": { + "attribute_name": "Created At", + "input_type": "date", + "data_type": "date", + "filter_operators": [ "is_greater_than", "is_less_than", "days_before" ], + "attribute_type": "date_attributes" } }, "contacts": { @@ -134,6 +148,20 @@ "data_type": "text", "filter_operators": ["exactly_equal_to", "contains", "does_not_contain" ], "attribute_type": "standard" + }, + "created_at": { + "attribute_name": "Created At", + "input_type": "date", + "data_type": "date", + "filter_operators": [ "is_greater_than", "is_less_than", "days_before" ], + "attribute_type": "date_attributes" + }, + "last_activity_at": { + "attribute_name": "Created At", + "input_type": "date", + "data_type": "date", + "filter_operators": [ "is_greater_than", "is_less_than", "days_before" ], + "attribute_type": "date_attributes" } }, "messages": { diff --git a/spec/services/contacts/filter_service_spec.rb b/spec/services/contacts/filter_service_spec.rb index f52a6c934..e4a05946a 100644 --- a/spec/services/contacts/filter_service_spec.rb +++ b/spec/services/contacts/filter_service_spec.rb @@ -141,6 +141,84 @@ describe ::Contacts::FilterService do expect(result[:contacts].length).to be 1 expect(result[:contacts].first.id).to eq(el_contact.id) end + + it 'filter by created_at and custom_attributes' do + tomorrow = Date.tomorrow.strftime + params[:payload] = [ + { + attribute_key: 'customer_type', + filter_operator: 'equal_to', + values: ['platinum'], + query_operator: 'AND' + }.with_indifferent_access, + { + attribute_key: 'created_at', + filter_operator: 'is_less_than', + values: [tomorrow.to_s], + query_operator: nil + }.with_indifferent_access + ] + result = filter_service.new(params, user_1).perform + expected_count = Contact.where("created_at < ? AND custom_attributes->>'customer_type' = ?", Date.tomorrow, 'platinum').count + + expect(result[:contacts].length).to be expected_count + expect(result[:contacts].first.id).to eq(el_contact.id) + end + + context 'with x_days_before filter' do + before do + el_contact.update(last_activity_at: (Time.zone.today - 4.days)) + cs_contact.update(last_activity_at: (Time.zone.today - 5.days)) + en_contact.update(last_activity_at: (Time.zone.today - 2.days)) + end + + it 'filter by last_activity_at 3_days_before and custom_attributes' do + params[:payload] = [ + { + attribute_key: 'last_activity_at', + filter_operator: 'days_before', + values: [3], + query_operator: 'AND' + }.with_indifferent_access, + { + attribute_key: 'contact_additional_information', + filter_operator: 'equal_to', + values: ['test custom data'], + query_operator: nil + }.with_indifferent_access + ] + + expected_count = Contact.where( + "last_activity_at < ? AND + custom_attributes->>'contact_additional_information' = ?", + (Time.zone.today - 3.days), + 'test custom data' + ).count + + result = filter_service.new(params, user_1).perform + expect(result[:contacts].length).to be expected_count + expect(result[:contacts].first.id).to eq(el_contact.id) + end + + it 'filter by last_activity_at 2_days_before and custom_attributes' do + params[:payload] = [ + { + attribute_key: 'last_activity_at', + filter_operator: 'days_before', + values: [2], + query_operator: nil + }.with_indifferent_access + ] + + expected_count = Contact.where('last_activity_at < ?', (Time.zone.today - 2.days)).count + + result = filter_service.new(params, user_1).perform + expect(result[:contacts].length).to be expected_count + expect(result[:contacts].pluck(:id)).to include(el_contact.id) + expect(result[:contacts].pluck(:id)).to include(cs_contact.id) + expect(result[:contacts].pluck(:id)).not_to include(en_contact.id) + end + end end end end diff --git a/spec/services/conversations/filter_service_spec.rb b/spec/services/conversations/filter_service_spec.rb index c199cd3e2..693bcf2a9 100644 --- a/spec/services/conversations/filter_service_spec.rb +++ b/spec/services/conversations/filter_service_spec.rb @@ -136,24 +136,35 @@ describe ::Conversations::FilterService do describe '#perform on custom attribute' do context 'with query present' do let!(:params) { { payload: [], page: 1 } } - let(:payload) do - [ + + it 'filter by custom_attributes and labels' do + user_2_assigned_conversation.update_labels('support') + params[:payload] = [ { - attribute_key: 'browser_language', - filter_operator: 'contains', - values: 'en', + attribute_key: 'conversation_type', + filter_operator: 'equal_to', + values: ['platinum'], query_operator: 'AND' }.with_indifferent_access, { - attribute_key: 'status', - filter_operator: 'not_equal_to', - values: %w[resolved], + attribute_key: 'conversation_created', + filter_operator: 'is_less_than', + values: ['2022-01-20'], + query_operator: 'OR' + }.with_indifferent_access, + { + attribute_key: 'labels', + filter_operator: 'equal_to', + values: ['support'], query_operator: nil }.with_indifferent_access ] + result = filter_service.new(params, user_1).perform + expect(result[:conversations].length).to be 1 + expect(result[:conversations][0][:id]).to be user_2_assigned_conversation.id end - it 'filter by custom_attributes and labels' do + it 'filter by custom_attributes' do params[:payload] = [ { attribute_key: 'conversation_type', @@ -171,6 +182,114 @@ describe ::Conversations::FilterService do result = filter_service.new(params, user_1).perform expect(result[:conversations].length).to be 1 end + + it 'filter by custom_attributes and additional_attributes' do + params[:payload] = [ + { + attribute_key: 'conversation_type', + filter_operator: 'equal_to', + values: ['platinum'], + query_operator: 'AND' + }.with_indifferent_access, + { + attribute_key: 'browser_language', + filter_operator: 'is_equal_to', + values: 'en', + query_operator: nil + }.with_indifferent_access + ] + result = filter_service.new(params, user_1).perform + expect(result[:conversations].length).to be 1 + end + end + end + + describe '#perform on date filter' do + context 'with query present' do + let!(:params) { { payload: [], page: 1 } } + + it 'filter by created_at' do + params[:payload] = [ + { + attribute_key: 'created_at', + filter_operator: 'is_greater_than', + values: ['2022-01-20'], + query_operator: nil + }.with_indifferent_access + ] + result = filter_service.new(params, user_1).perform + expected_count = Conversation.where('created_at > ?', DateTime.parse('2022-01-20')).count + expect(result[:conversations].length).to be expected_count + end + + it 'filter by created_at and conversation_type' do + params[:payload] = [ + { + attribute_key: 'conversation_type', + filter_operator: 'equal_to', + values: ['platinum'], + query_operator: 'AND' + }.with_indifferent_access, + { + attribute_key: 'created_at', + filter_operator: 'is_greater_than', + values: ['2022-01-20'], + query_operator: nil + }.with_indifferent_access + ] + result = filter_service.new(params, user_1).perform + expected_count = Conversation.where("created_at > ? AND custom_attributes->>'conversation_type' = ?", DateTime.parse('2022-01-20'), + 'platinum').count + + expect(result[:conversations].length).to be expected_count + end + + context 'with x_days_before filter' do + before do + en_conversation_1.update!(last_activity_at: (Time.zone.today - 4.days)) + en_conversation_2.update!(last_activity_at: (Time.zone.today - 5.days)) + user_2_assigned_conversation.update!(last_activity_at: (Time.zone.today - 2.days)) + end + + it 'filter by last_activity_at 3_days_before and custom_attributes' do + params[:payload] = [ + { + attribute_key: 'last_activity_at', + filter_operator: 'days_before', + values: [3], + query_operator: 'AND' + }.with_indifferent_access, + { + attribute_key: 'conversation_type', + filter_operator: 'equal_to', + values: ['platinum'], + query_operator: nil + }.with_indifferent_access + ] + + expected_count = Conversation.where("last_activity_at < ? AND custom_attributes->>'conversation_type' = ?", (Time.zone.today - 3.days), + 'platinum').count + + result = filter_service.new(params, user_1).perform + expect(result[:conversations].length).to be expected_count + end + + it 'filter by last_activity_at 2_days_before' do + params[:payload] = [ + { + attribute_key: 'last_activity_at', + filter_operator: 'days_before', + values: [3], + query_operator: nil + }.with_indifferent_access + ] + + expected_count = Conversation.where('last_activity_at < ?', (Time.zone.today - 2.days)).count + + result = filter_service.new(params, user_1).perform + expect(result[:conversations].length).to be expected_count + end + end end end end