Add first_reply_created event in conversation (#4576)

This commit is contained in:
Aswin Dev P.S 2022-05-19 09:46:33 +05:30 committed by GitHub
parent 20565d09c0
commit 8538660bbd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 117 additions and 22 deletions

View file

@ -0,0 +1,17 @@
# Delete migration and spec after 2 consecutive releases.
class Migration::ConversationsFirstReplySchedulerJob < ApplicationJob
queue_as :scheduled_jobs
def perform(account)
account.conversations.each do |conversation|
# rubocop:disable Rails/SkipsModelValidations
if conversation.messages.outgoing.where("(additional_attributes->'campaign_id') is null").count.positive?
conversation.update_columns(first_reply_created_at: conversation.messages.outgoing.where("(additional_attributes->'campaign_id') is null")
.first.created_at)
else
conversation.update_columns(first_reply_created_at: nil)
end
# rubocop:enable Rails/SkipsModelValidations
end
end
end

View file

@ -36,6 +36,9 @@ class ReportingEventListener < BaseListener
event_start_time: conversation.created_at, event_start_time: conversation.created_at,
event_end_time: message.created_at event_end_time: message.created_at
) )
# rubocop:disable Rails/SkipsModelValidations
conversation.update_columns(first_reply_created_at: message.created_at)
# rubocop:enable Rails/SkipsModelValidations
reporting_event.save reporting_event.save
end end
end end

View file

@ -8,6 +8,7 @@
# assignee_last_seen_at :datetime # assignee_last_seen_at :datetime
# contact_last_seen_at :datetime # contact_last_seen_at :datetime
# custom_attributes :jsonb # custom_attributes :jsonb
# first_reply_created_at :datetime
# identifier :string # identifier :string
# last_activity_at :datetime not null # last_activity_at :datetime not null
# snoozed_until :datetime # snoozed_until :datetime
@ -31,6 +32,7 @@
# index_conversations_on_assignee_id_and_account_id (assignee_id,account_id) # index_conversations_on_assignee_id_and_account_id (assignee_id,account_id)
# index_conversations_on_campaign_id (campaign_id) # index_conversations_on_campaign_id (campaign_id)
# index_conversations_on_contact_inbox_id (contact_inbox_id) # index_conversations_on_contact_inbox_id (contact_inbox_id)
# index_conversations_on_first_reply_created_at (first_reply_created_at)
# index_conversations_on_last_activity_at (last_activity_at) # index_conversations_on_last_activity_at (last_activity_at)
# index_conversations_on_status_and_account_id (status,account_id) # index_conversations_on_status_and_account_id (status,account_id)
# index_conversations_on_team_id (team_id) # index_conversations_on_team_id (team_id)

View file

@ -0,0 +1,23 @@
class AddFirstReplyActivityAtToConversation < ActiveRecord::Migration[6.1]
def change
add_column :conversations, :first_reply_created_at, :datetime
add_index :conversations, :first_reply_created_at
# rubocop:disable Rails/SkipsModelValidations
::Conversation.update_all(first_reply_created_at: Time.now.utc)
# rubocop:enable Rails/SkipsModelValidations
backfill_first_reply_activity_at_to_conversations
end
private
def backfill_first_reply_activity_at_to_conversations
::Account.find_in_batches do |account_batch|
Rails.logger.info "Migrated till #{account_batch.first.id}\n"
account_batch.each do |account|
Migration::ConversationsFirstReplySchedulerJob.perform_later(account)
end
end
end
end

View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2022_05_11_072655) do ActiveRecord::Schema.define(version: 2022_05_13_145010) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements" enable_extension "pg_stat_statements"
@ -385,11 +385,13 @@ ActiveRecord::Schema.define(version: 2022_05_11_072655) do
t.datetime "snoozed_until" t.datetime "snoozed_until"
t.jsonb "custom_attributes", default: {} t.jsonb "custom_attributes", default: {}
t.datetime "assignee_last_seen_at" t.datetime "assignee_last_seen_at"
t.datetime "first_reply_created_at"
t.index ["account_id", "display_id"], name: "index_conversations_on_account_id_and_display_id", unique: true t.index ["account_id", "display_id"], name: "index_conversations_on_account_id_and_display_id", unique: true
t.index ["account_id"], name: "index_conversations_on_account_id" t.index ["account_id"], name: "index_conversations_on_account_id"
t.index ["assignee_id", "account_id"], name: "index_conversations_on_assignee_id_and_account_id" t.index ["assignee_id", "account_id"], name: "index_conversations_on_assignee_id_and_account_id"
t.index ["campaign_id"], name: "index_conversations_on_campaign_id" t.index ["campaign_id"], name: "index_conversations_on_campaign_id"
t.index ["contact_inbox_id"], name: "index_conversations_on_contact_inbox_id" t.index ["contact_inbox_id"], name: "index_conversations_on_contact_inbox_id"
t.index ["first_reply_created_at"], name: "index_conversations_on_first_reply_created_at"
t.index ["last_activity_at"], name: "index_conversations_on_last_activity_at" t.index ["last_activity_at"], name: "index_conversations_on_last_activity_at"
t.index ["status", "account_id"], name: "index_conversations_on_status_and_account_id" t.index ["status", "account_id"], name: "index_conversations_on_status_and_account_id"
t.index ["team_id"], name: "index_conversations_on_team_id" t.index ["team_id"], name: "index_conversations_on_team_id"

View file

@ -0,0 +1,48 @@
require 'rails_helper'
RSpec.describe Migration::ConversationsFirstReplySchedulerJob, type: :job do
subject(:job) { described_class.perform_later }
let!(:account) { create(:account) }
let!(:inbox) { create(:inbox, account: account) }
let!(:user) { create(:user, account: account) }
it 'enqueues the job' do
expect { job }.to have_enqueued_job(described_class)
.on_queue('scheduled_jobs')
end
context 'when there is an outgoing message in conversation' do
let!(:conversation) { create(:conversation, account: account, inbox: inbox, assignee: user) }
let!(:message) do
create(:message, content: 'Hi', message_type: 'outgoing', account: account, inbox: inbox,
conversation: conversation)
end
it 'updates the conversation first reply with the first outgoing message created time' do
create(:message, content: 'Hello', message_type: 'outgoing', account: account, inbox: inbox,
conversation: conversation)
described_class.perform_now(account)
conversation.reload
expect(conversation.messages.count).to eq 2
expect(conversation.first_reply_created_at.to_i).to eq message.created_at.to_i
end
end
context 'when there is no outgoing message in conversation' do
let!(:conversation) { create(:conversation, account: account, inbox: inbox, assignee: user) }
it 'updates the conversation first reply with nil' do
create(:message, content: 'Hello', message_type: 'incoming', account: account, inbox: inbox,
conversation: conversation)
described_class.perform_now(account)
conversation.reload
expect(conversation.messages.count).to eq 1
expect(conversation.first_reply_created_at).to be_nil
end
end
end