diff --git a/app/controllers/api/v1/accounts/conversations/assignments_controller.rb b/app/controllers/api/v1/accounts/conversations/assignments_controller.rb index 68ff2e67d..1fb2095e3 100644 --- a/app/controllers/api/v1/accounts/conversations/assignments_controller.rb +++ b/app/controllers/api/v1/accounts/conversations/assignments_controller.rb @@ -14,7 +14,8 @@ class Api::V1::Accounts::Conversations::AssignmentsController < Api::V1::Account def set_agent @agent = Current.account.users.find_by(id: params[:assignee_id]) - @conversation.update_assignee(@agent) + @conversation.assignee = @agent + @conversation.save! render_agent end diff --git a/app/controllers/api/v1/accounts/conversations_controller.rb b/app/controllers/api/v1/accounts/conversations_controller.rb index eb3187d54..a3d3ad645 100644 --- a/app/controllers/api/v1/accounts/conversations_controller.rb +++ b/app/controllers/api/v1/accounts/conversations_controller.rb @@ -110,8 +110,8 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro end def assign_conversation - @agent = Current.account.users.find(current_user.id) - @conversation.update_assignee(@agent) + @conversation.assignee = current_user + @conversation.save! end def conversation diff --git a/app/jobs/migration/conversation_cache_label_job.rb b/app/jobs/migration/conversation_cache_label_job.rb new file mode 100644 index 000000000..1ae5a3b70 --- /dev/null +++ b/app/jobs/migration/conversation_cache_label_job.rb @@ -0,0 +1,16 @@ +class Migration::ConversationCacheLabelJob < ApplicationJob + queue_as :async_database_migration + + # To cache the label, we simply access it from the object and save it. Anytime the object is + # saved in the future, ActsAsTaggable will automatically recompute it. This process is done + # initially when the user has not performed any action. + # Reference: https://github.com/mbleigh/acts-as-taggable-on/wiki/Caching + def perform(account) + account.conversations.find_in_batches do |conversation_batch| + conversation_batch.each do |conversation| + conversation.label_list + conversation.save! + end + end + end +end diff --git a/app/models/conversation.rb b/app/models/conversation.rb index 88a837c26..5243bbbd9 100644 --- a/app/models/conversation.rb +++ b/app/models/conversation.rb @@ -6,6 +6,7 @@ # additional_attributes :jsonb # agent_last_seen_at :datetime # assignee_last_seen_at :datetime +# cached_label_list :string # contact_last_seen_at :datetime # custom_attributes :jsonb # first_reply_created_at :datetime @@ -144,10 +145,6 @@ class Conversation < ApplicationRecord end end - def update_assignee(agent = nil) - update!(assignee: agent) - end - def toggle_status # FIXME: implement state machine with aasm self.status = open? ? :resolved : :open @@ -185,6 +182,10 @@ class Conversation < ApplicationRecord Conversations::EventDataPresenter.new(self).push_data end + def cached_label_list_array + (cached_label_list || '').split(',') + end + def notifiable_assignee_change? return false unless saved_change_to_assignee_id? return false if assignee_id.blank? diff --git a/app/views/api/v1/accounts/conversations/messages/index.json.jbuilder b/app/views/api/v1/accounts/conversations/messages/index.json.jbuilder index e1a3e1125..2a1511d2f 100644 --- a/app/views/api/v1/accounts/conversations/messages/index.json.jbuilder +++ b/app/views/api/v1/accounts/conversations/messages/index.json.jbuilder @@ -1,5 +1,5 @@ json.meta do - json.labels @conversation.label_list + json.labels @conversation.cached_label_list_array json.additional_attributes @conversation.additional_attributes json.contact @conversation.contact.push_event_data json.assignee @conversation.assignee.push_event_data if @conversation.assignee.present? diff --git a/app/views/api/v1/conversations/partials/_conversation.json.jbuilder b/app/views/api/v1/conversations/partials/_conversation.json.jbuilder index eaa5097c3..cef56fed4 100644 --- a/app/views/api/v1/conversations/partials/_conversation.json.jbuilder +++ b/app/views/api/v1/conversations/partials/_conversation.json.jbuilder @@ -35,7 +35,7 @@ json.can_reply conversation.can_reply? json.contact_last_seen_at conversation.contact_last_seen_at.to_i json.custom_attributes conversation.custom_attributes json.inbox_id conversation.inbox_id -json.labels conversation.label_list +json.labels conversation.cached_label_list_array json.muted conversation.muted? json.snoozed_until conversation.snoozed_until json.status conversation.status diff --git a/db/migrate/20231211010807_add_cached_labels_list.rb b/db/migrate/20231211010807_add_cached_labels_list.rb new file mode 100644 index 000000000..02f01a7ea --- /dev/null +++ b/db/migrate/20231211010807_add_cached_labels_list.rb @@ -0,0 +1,19 @@ +class AddCachedLabelsList < ActiveRecord::Migration[7.0] + def change + add_column :conversations, :cached_label_list, :string + Conversation.reset_column_information + ActsAsTaggableOn::Taggable::Cache.included(Conversation) + + update_exisiting_conversations + end + + private + + def update_exisiting_conversations + ::Account.find_in_batches do |account_batch| + account_batch.each do |account| + Migration::ConversationCacheLabelJob.perform_later(account) + end + end + end +end diff --git a/db/schema.rb b/db/schema.rb index fe58aba72..61fd7e0d3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_12_01_014644) do +ActiveRecord::Schema[7.0].define(version: 2023_12_11_010807) do # These are extensions that must be enabled in order to support this database enable_extension "pg_stat_statements" enable_extension "pg_trgm" @@ -453,6 +453,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_12_01_014644) do t.integer "priority" t.bigint "sla_policy_id" t.datetime "waiting_since" + t.string "cached_label_list" t.index ["account_id", "display_id"], name: "index_conversations_on_account_id_and_display_id", unique: true t.index ["account_id", "id"], name: "index_conversations_on_id_and_account_id" t.index ["account_id", "inbox_id", "status", "assignee_id"], name: "conv_acid_inbid_stat_asgnid_idx" diff --git a/spec/models/concerns/assignment_handler_shared.rb b/spec/models/concerns/assignment_handler_shared.rb index 55951cd99..8447b8146 100644 --- a/spec/models/concerns/assignment_handler_shared.rb +++ b/spec/models/concerns/assignment_handler_shared.rb @@ -63,47 +63,4 @@ shared_examples_for 'assignment_handler' do end end end - - describe '#update_assignee' do - subject(:update_assignee) { conversation.update_assignee(agent) } - - let(:conversation) { create(:conversation, assignee: nil) } - let(:agent) do - create(:user, email: 'agent@example.com', account: conversation.account, role: :agent) - end - let(:assignment_mailer) { instance_double(AgentNotifications::ConversationNotificationsMailer, deliver: true) } - - before do - create(:inbox_member, user: agent, inbox: conversation.inbox) - end - - it 'assigns the agent to conversation' do - expect(update_assignee).to be(true) - expect(conversation.reload.assignee).to eq(agent) - end - - it 'dispaches assignee changed event' do - # TODO: FIX me - # expect(EventDispatcherJob).to(have_been_enqueued.at_least(:once).with('assignee.changed', anything, anything, anything, anything)) - expect(EventDispatcherJob).to(have_been_enqueued.at_least(:once)) - expect(update_assignee).to be(true) - end - - it 'adds assignee to conversation participants' do - expect { update_assignee }.to change { conversation.conversation_participants.count }.by(1) - end - - context 'when agent is current user' do - before do - Current.user = agent - end - - it 'creates self-assigned message activity' do - expect(update_assignee).to be(true) - expect(Conversations::ActivityMessageJob).to(have_been_enqueued.at_least(:once) - .with(conversation, { account_id: conversation.account_id, inbox_id: conversation.inbox_id, - message_type: :activity, content: "#{agent.name} self-assigned this conversation" })) - end - end - end end