Add first_reply_created event in conversation (#4576)
This commit is contained in:
parent
20565d09c0
commit
8538660bbd
6 changed files with 117 additions and 22 deletions
|
@ -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
|
|
@ -36,6 +36,9 @@ class ReportingEventListener < BaseListener
|
|||
event_start_time: conversation.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
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,27 +2,28 @@
|
|||
#
|
||||
# Table name: conversations
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# additional_attributes :jsonb
|
||||
# agent_last_seen_at :datetime
|
||||
# assignee_last_seen_at :datetime
|
||||
# contact_last_seen_at :datetime
|
||||
# custom_attributes :jsonb
|
||||
# identifier :string
|
||||
# last_activity_at :datetime not null
|
||||
# snoozed_until :datetime
|
||||
# status :integer default("open"), not null
|
||||
# uuid :uuid not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :integer not null
|
||||
# assignee_id :integer
|
||||
# campaign_id :bigint
|
||||
# contact_id :bigint
|
||||
# contact_inbox_id :bigint
|
||||
# display_id :integer not null
|
||||
# inbox_id :integer not null
|
||||
# team_id :bigint
|
||||
# id :integer not null, primary key
|
||||
# additional_attributes :jsonb
|
||||
# agent_last_seen_at :datetime
|
||||
# assignee_last_seen_at :datetime
|
||||
# contact_last_seen_at :datetime
|
||||
# custom_attributes :jsonb
|
||||
# first_reply_created_at :datetime
|
||||
# identifier :string
|
||||
# last_activity_at :datetime not null
|
||||
# snoozed_until :datetime
|
||||
# status :integer default("open"), not null
|
||||
# uuid :uuid not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :integer not null
|
||||
# assignee_id :integer
|
||||
# campaign_id :bigint
|
||||
# contact_id :bigint
|
||||
# contact_inbox_id :bigint
|
||||
# display_id :integer not null
|
||||
# inbox_id :integer not null
|
||||
# team_id :bigint
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
@ -31,6 +32,7 @@
|
|||
# index_conversations_on_assignee_id_and_account_id (assignee_id,account_id)
|
||||
# index_conversations_on_campaign_id (campaign_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_status_and_account_id (status,account_id)
|
||||
# index_conversations_on_team_id (team_id)
|
||||
|
|
|
@ -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
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# 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
|
||||
enable_extension "pg_stat_statements"
|
||||
|
@ -385,11 +385,13 @@ ActiveRecord::Schema.define(version: 2022_05_11_072655) do
|
|||
t.datetime "snoozed_until"
|
||||
t.jsonb "custom_attributes", default: {}
|
||||
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"], name: "index_conversations_on_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 ["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 ["status", "account_id"], name: "index_conversations_on_status_and_account_id"
|
||||
t.index ["team_id"], name: "index_conversations_on_team_id"
|
||||
|
|
|
@ -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
|
Loading…
Reference in a new issue