Compare commits
11 commits
develop
...
chore/4285
Author | SHA1 | Date | |
---|---|---|---|
|
37d6430b6a | ||
|
10d0eb063f | ||
|
2d36d3879d | ||
|
d2e200e21f | ||
|
b9175b5877 | ||
|
267b19db3d | ||
|
e04a0012f3 | ||
|
f32f1d22a3 | ||
|
3dac404a19 | ||
|
9882424616 | ||
|
8ba8752bf6 |
23 changed files with 93 additions and 115 deletions
|
@ -183,3 +183,4 @@ AllCops:
|
|||
- db/migrate/20200503151130_add_account_feature_flag.rb
|
||||
- db/migrate/20200927135222_add_last_activity_at_to_conversation.rb
|
||||
- db/migrate/20210306170117_add_last_activity_at_to_contacts.rb
|
||||
- db/migrate/20220809104508_revert_cascading_indexes.rb
|
||||
|
|
19
app/jobs/migration/remove_stale_notifications_job.rb
Normal file
19
app/jobs/migration/remove_stale_notifications_job.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Delete migration and spec after 2 consecutive releases.
|
||||
class Migration::RemoveStaleNotificationsJob < ApplicationJob
|
||||
queue_as :scheduled_jobs
|
||||
|
||||
def perform
|
||||
remove_invalid_messages
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def remove_invalid_messages
|
||||
deleted_ids = []
|
||||
Message.unscoped.distinct.pluck(:inbox_id).each_slice(1000) do |id_list|
|
||||
deleted_ids << (id_list - Inbox.where(id: id_list).pluck(:id))
|
||||
end
|
||||
|
||||
Message.where(inbox_id: deleted_ids.flatten).destroy_all
|
||||
end
|
||||
end
|
|
@ -55,7 +55,7 @@ class Account < ApplicationRecord
|
|||
has_many :csat_survey_responses, dependent: :destroy_async
|
||||
has_many :custom_attribute_definitions, dependent: :destroy_async
|
||||
has_many :custom_filters, dependent: :destroy_async
|
||||
has_many :dashboard_apps, dependent: :destroy
|
||||
has_many :dashboard_apps, dependent: :destroy_async
|
||||
has_many :data_imports, dependent: :destroy_async
|
||||
has_many :email_channels, dependent: :destroy_async, class_name: '::Channel::Email'
|
||||
has_many :facebook_pages, dependent: :destroy_async, class_name: '::Channel::FacebookPage'
|
||||
|
@ -67,7 +67,7 @@ class Account < ApplicationRecord
|
|||
has_many :messages, dependent: :destroy_async
|
||||
has_many :notes, dependent: :destroy_async
|
||||
has_many :notification_settings, dependent: :destroy_async
|
||||
has_many :notifications, dependent: :destroy
|
||||
has_many :notifications, dependent: :destroy_async
|
||||
has_many :portals, dependent: :destroy_async, class_name: '::Portal'
|
||||
has_many :sms_channels, dependent: :destroy_async, class_name: '::Channel::Sms'
|
||||
has_many :teams, dependent: :destroy_async
|
||||
|
|
|
@ -19,11 +19,6 @@
|
|||
# index_account_users_on_user_id (user_id)
|
||||
# uniq_user_id_per_account_id (account_id,user_id) UNIQUE
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (account_id => accounts.id) ON DELETE => cascade
|
||||
# fk_rails_... (user_id => users.id) ON DELETE => cascade
|
||||
#
|
||||
|
||||
class AccountUser < ApplicationRecord
|
||||
include AvailabilityStatusable
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
#
|
||||
# index_agent_bots_on_account_id (account_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (account_id => accounts.id) ON DELETE => cascade
|
||||
#
|
||||
|
||||
class AgentBot < ApplicationRecord
|
||||
include AccessTokenable
|
||||
|
|
|
@ -23,11 +23,6 @@
|
|||
# index_articles_on_associated_article_id (associated_article_id)
|
||||
# index_articles_on_author_id (author_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (associated_article_id => articles.id)
|
||||
# fk_rails_... (author_id => users.id)
|
||||
#
|
||||
class Article < ApplicationRecord
|
||||
include PgSearch::Model
|
||||
|
||||
|
|
|
@ -28,11 +28,6 @@
|
|||
# index_campaigns_on_inbox_id (inbox_id)
|
||||
# index_campaigns_on_scheduled_at (scheduled_at)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (account_id => accounts.id) ON DELETE => cascade
|
||||
# fk_rails_... (inbox_id => inboxes.id) ON DELETE => cascade
|
||||
#
|
||||
class Campaign < ApplicationRecord
|
||||
include UrlHelper
|
||||
validates :account_id, presence: true
|
||||
|
|
|
@ -23,11 +23,6 @@
|
|||
# index_categories_on_parent_category_id (parent_category_id)
|
||||
# index_categories_on_slug_and_locale_and_portal_id (slug,locale,portal_id) UNIQUE
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (associated_category_id => categories.id)
|
||||
# fk_rails_... (parent_category_id => categories.id)
|
||||
#
|
||||
class Category < ApplicationRecord
|
||||
belongs_to :account
|
||||
belongs_to :portal
|
||||
|
|
|
@ -19,11 +19,6 @@
|
|||
# index_contact_inboxes_on_pubsub_token (pubsub_token) UNIQUE
|
||||
# index_contact_inboxes_on_source_id (source_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (contact_id => contacts.id) ON DELETE => cascade
|
||||
# fk_rails_... (inbox_id => inboxes.id) ON DELETE => cascade
|
||||
#
|
||||
|
||||
class ContactInbox < ApplicationRecord
|
||||
include Pubsubable
|
||||
|
|
|
@ -37,12 +37,6 @@
|
|||
# index_conversations_on_status_and_account_id (status,account_id)
|
||||
# index_conversations_on_team_id (team_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (campaign_id => campaigns.id) ON DELETE => cascade
|
||||
# fk_rails_... (contact_inbox_id => contact_inboxes.id) ON DELETE => cascade
|
||||
# fk_rails_... (team_id => teams.id) ON DELETE => cascade
|
||||
#
|
||||
|
||||
class Conversation < ApplicationRecord
|
||||
include Labelable
|
||||
|
@ -88,7 +82,7 @@ class Conversation < ApplicationRecord
|
|||
has_many :mentions, dependent: :destroy_async
|
||||
has_many :messages, dependent: :destroy_async, autosave: true
|
||||
has_one :csat_survey_response, dependent: :destroy_async
|
||||
has_many :notifications, as: :primary_actor, dependent: :destroy
|
||||
has_many :notifications, as: :primary_actor, dependent: :destroy_async
|
||||
|
||||
before_save :ensure_snooze_until_reset
|
||||
before_create :mark_conversation_pending_if_bot
|
||||
|
|
|
@ -21,14 +21,6 @@
|
|||
# index_csat_survey_responses_on_conversation_id (conversation_id)
|
||||
# index_csat_survey_responses_on_message_id (message_id) UNIQUE
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (account_id => accounts.id) ON DELETE => cascade
|
||||
# fk_rails_... (assigned_agent_id => users.id) ON DELETE => cascade
|
||||
# fk_rails_... (contact_id => contacts.id) ON DELETE => cascade
|
||||
# fk_rails_... (conversation_id => conversations.id) ON DELETE => cascade
|
||||
# fk_rails_... (message_id => messages.id) ON DELETE => cascade
|
||||
#
|
||||
class CsatSurveyResponse < ApplicationRecord
|
||||
belongs_to :account
|
||||
belongs_to :conversation
|
||||
|
|
|
@ -15,11 +15,6 @@
|
|||
# index_dashboard_apps_on_account_id (account_id)
|
||||
# index_dashboard_apps_on_user_id (user_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (account_id => accounts.id)
|
||||
# fk_rails_... (user_id => users.id)
|
||||
#
|
||||
class DashboardApp < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :account
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
#
|
||||
# index_data_imports_on_account_id (account_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (account_id => accounts.id) ON DELETE => cascade
|
||||
#
|
||||
class DataImport < ApplicationRecord
|
||||
belongs_to :account
|
||||
validates :data_type, inclusion: { in: ['contacts'], message: I18n.t('errors.data_import.data_type.invalid') }
|
||||
|
|
|
@ -18,11 +18,6 @@
|
|||
# index_macros_on_created_by_id (created_by_id)
|
||||
# index_macros_on_updated_by_id (updated_by_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (created_by_id => users.id)
|
||||
# fk_rails_... (updated_by_id => users.id)
|
||||
#
|
||||
class Macro < ApplicationRecord
|
||||
belongs_to :account
|
||||
belongs_to :created_by,
|
||||
|
|
|
@ -17,11 +17,6 @@
|
|||
# index_mentions_on_user_id (user_id)
|
||||
# index_mentions_on_user_id_and_conversation_id (user_id,conversation_id) UNIQUE
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (conversation_id => conversations.id) ON DELETE => cascade
|
||||
# fk_rails_... (user_id => users.id) ON DELETE => cascade
|
||||
#
|
||||
class Mention < ApplicationRecord
|
||||
include SortHandler
|
||||
|
||||
|
|
|
@ -85,8 +85,9 @@ class Message < ApplicationRecord
|
|||
belongs_to :contact, required: false
|
||||
belongs_to :sender, polymorphic: true, required: false
|
||||
|
||||
has_many :attachments, dependent: :destroy_async, autosave: true, before_add: :validate_attachments_limit
|
||||
has_many :attachments, dependent: :destroy, autosave: true, before_add: :validate_attachments_limit
|
||||
has_one :csat_survey_response, dependent: :destroy_async
|
||||
has_many :notifications, as: :primary_actor, dependent: :destroy_async
|
||||
|
||||
after_create_commit :execute_after_create_commit_callbacks
|
||||
|
||||
|
|
|
@ -16,12 +16,6 @@
|
|||
# index_notes_on_contact_id (contact_id)
|
||||
# index_notes_on_user_id (user_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (account_id => accounts.id) ON DELETE => cascade
|
||||
# fk_rails_... (contact_id => contacts.id) ON DELETE => cascade
|
||||
# fk_rails_... (user_id => users.id) ON DELETE => cascade
|
||||
#
|
||||
class Note < ApplicationRecord
|
||||
before_validation :ensure_account_id
|
||||
validates :content, presence: true
|
||||
|
|
|
@ -15,10 +15,6 @@
|
|||
# index_teams_on_account_id (account_id)
|
||||
# index_teams_on_name_and_account_id (name,account_id) UNIQUE
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (account_id => accounts.id) ON DELETE => cascade
|
||||
#
|
||||
class Team < ApplicationRecord
|
||||
belongs_to :account
|
||||
has_many :team_members, dependent: :destroy_async
|
||||
|
|
|
@ -14,11 +14,6 @@
|
|||
# index_team_members_on_team_id_and_user_id (team_id,user_id) UNIQUE
|
||||
# index_team_members_on_user_id (user_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (team_id => teams.id) ON DELETE => cascade
|
||||
# fk_rails_... (user_id => users.id) ON DELETE => cascade
|
||||
#
|
||||
class TeamMember < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :team
|
||||
|
|
46
db/migrate/20220809104508_revert_cascading_indexes.rb
Normal file
46
db/migrate/20220809104508_revert_cascading_indexes.rb
Normal file
|
@ -0,0 +1,46 @@
|
|||
class RevertCascadingIndexes < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
remove_foreign_key 'account_users', 'accounts' if foreign_key_exists? 'account_users', 'accounts'
|
||||
remove_foreign_key 'account_users', 'users' if foreign_key_exists? 'account_users', 'users'
|
||||
remove_foreign_key 'agent_bots', 'accounts' if foreign_key_exists? 'agent_bots', 'accounts'
|
||||
remove_foreign_key 'campaigns', 'accounts' if foreign_key_exists? 'campaigns', 'accounts'
|
||||
remove_foreign_key 'campaigns', 'inboxes' if foreign_key_exists? 'campaigns', 'inboxes'
|
||||
remove_foreign_key 'conversations', 'campaigns' if foreign_key_exists? 'conversations', 'campaigns'
|
||||
remove_foreign_key 'conversations', 'contact_inboxes' if foreign_key_exists? 'conversations', 'contact_inboxes'
|
||||
remove_foreign_key 'conversations', 'teams' if foreign_key_exists? 'conversations', 'teams'
|
||||
remove_foreign_key 'csat_survey_responses', 'accounts' if foreign_key_exists? 'csat_survey_responses', 'accounts'
|
||||
remove_foreign_key 'csat_survey_responses', 'contacts' if foreign_key_exists? 'csat_survey_responses', 'contacts'
|
||||
remove_foreign_key 'csat_survey_responses', 'conversations' if foreign_key_exists? 'csat_survey_responses', 'conversations'
|
||||
remove_foreign_key 'csat_survey_responses', 'messages' if foreign_key_exists? 'csat_survey_responses', 'messages'
|
||||
remove_foreign_key 'csat_survey_responses', 'users', column: 'assigned_agent_id' if foreign_key_exists? 'csat_survey_responses', 'users',
|
||||
column: 'assigned_agent_id'
|
||||
remove_foreign_key 'data_imports', 'accounts' if foreign_key_exists? 'data_imports', 'accounts'
|
||||
remove_foreign_key 'mentions', 'conversations' if foreign_key_exists? 'mentions', 'conversations'
|
||||
remove_foreign_key 'mentions', 'users' if foreign_key_exists? 'mentions', 'users'
|
||||
remove_foreign_key 'notes', 'accounts' if foreign_key_exists? 'notes', 'accounts'
|
||||
remove_foreign_key 'notes', 'contacts' if foreign_key_exists? 'notes', 'contacts'
|
||||
remove_foreign_key 'notes', 'users' if foreign_key_exists? 'notes', 'users'
|
||||
remove_foreign_key 'team_members', 'teams' if foreign_key_exists? 'team_members', 'teams'
|
||||
remove_foreign_key 'team_members', 'users' if foreign_key_exists? 'team_members', 'users'
|
||||
remove_foreign_key 'teams', 'accounts' if foreign_key_exists? 'teams', 'accounts'
|
||||
remove_foreign_key 'contact_inboxes', 'contacts' if foreign_key_exists? 'contact_inboxes', 'contacts'
|
||||
remove_foreign_key 'contact_inboxes', 'inboxes' if foreign_key_exists? 'contact_inboxes', 'inboxes'
|
||||
|
||||
remove_foreign_key 'articles', 'articles', column: 'associated_article_id' if foreign_key_exists? 'articles', 'articles',
|
||||
column: 'associated_article_id'
|
||||
remove_foreign_key 'articles', 'users', column: 'author_id' if foreign_key_exists? 'articles', 'users', column: 'author_id'
|
||||
|
||||
remove_foreign_key 'categories', 'categories', column: 'parent_category_id' if foreign_key_exists? 'categories', 'categories',
|
||||
column: 'parent_category_id'
|
||||
remove_foreign_key 'categories', 'categories', column: 'associated_category_id' if foreign_key_exists? 'categories', 'categories',
|
||||
column: 'associated_category_id'
|
||||
|
||||
remove_foreign_key 'dashboard_apps', 'accounts' if foreign_key_exists? 'dashboard_apps', 'accounts'
|
||||
remove_foreign_key 'dashboard_apps', 'users' if foreign_key_exists? 'dashboard_apps', 'users'
|
||||
|
||||
remove_foreign_key 'macros', 'users', column: 'created_by_id' if foreign_key_exists? 'macros', 'users', column: 'created_by_id'
|
||||
remove_foreign_key 'macros', 'users', column: 'updated_by_id' if foreign_key_exists? 'macros', 'users', column: 'updated_by_id'
|
||||
|
||||
Migration::RemoveStaleNotificationsJob.perform_later
|
||||
end
|
||||
end
|
34
db/schema.rb
34
db/schema.rb
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2022_08_02_133722) do
|
||||
ActiveRecord::Schema.define(version: 2022_08_09_104508) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pg_stat_statements"
|
||||
|
@ -862,40 +862,8 @@ ActiveRecord::Schema.define(version: 2022_08_02_133722) do
|
|||
t.index ["inbox_id"], name: "index_working_hours_on_inbox_id"
|
||||
end
|
||||
|
||||
add_foreign_key "account_users", "accounts", on_delete: :cascade
|
||||
add_foreign_key "account_users", "users", on_delete: :cascade
|
||||
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
|
||||
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
|
||||
add_foreign_key "agent_bots", "accounts", on_delete: :cascade
|
||||
add_foreign_key "articles", "articles", column: "associated_article_id"
|
||||
add_foreign_key "articles", "users", column: "author_id"
|
||||
add_foreign_key "campaigns", "accounts", on_delete: :cascade
|
||||
add_foreign_key "campaigns", "inboxes", on_delete: :cascade
|
||||
add_foreign_key "categories", "categories", column: "associated_category_id"
|
||||
add_foreign_key "categories", "categories", column: "parent_category_id"
|
||||
add_foreign_key "contact_inboxes", "contacts", on_delete: :cascade
|
||||
add_foreign_key "contact_inboxes", "inboxes", on_delete: :cascade
|
||||
add_foreign_key "conversations", "campaigns", on_delete: :cascade
|
||||
add_foreign_key "conversations", "contact_inboxes", on_delete: :cascade
|
||||
add_foreign_key "conversations", "teams", on_delete: :cascade
|
||||
add_foreign_key "csat_survey_responses", "accounts", on_delete: :cascade
|
||||
add_foreign_key "csat_survey_responses", "contacts", on_delete: :cascade
|
||||
add_foreign_key "csat_survey_responses", "conversations", on_delete: :cascade
|
||||
add_foreign_key "csat_survey_responses", "messages", on_delete: :cascade
|
||||
add_foreign_key "csat_survey_responses", "users", column: "assigned_agent_id", on_delete: :cascade
|
||||
add_foreign_key "dashboard_apps", "accounts"
|
||||
add_foreign_key "dashboard_apps", "users"
|
||||
add_foreign_key "data_imports", "accounts", on_delete: :cascade
|
||||
add_foreign_key "macros", "users", column: "created_by_id"
|
||||
add_foreign_key "macros", "users", column: "updated_by_id"
|
||||
add_foreign_key "mentions", "conversations", on_delete: :cascade
|
||||
add_foreign_key "mentions", "users", on_delete: :cascade
|
||||
add_foreign_key "notes", "accounts", on_delete: :cascade
|
||||
add_foreign_key "notes", "contacts", on_delete: :cascade
|
||||
add_foreign_key "notes", "users", on_delete: :cascade
|
||||
add_foreign_key "team_members", "teams", on_delete: :cascade
|
||||
add_foreign_key "team_members", "users", on_delete: :cascade
|
||||
add_foreign_key "teams", "accounts", on_delete: :cascade
|
||||
create_trigger("accounts_after_insert_row_tr", :generated => true, :compatibility => 1).
|
||||
on("accounts").
|
||||
after(:insert).
|
||||
|
|
|
@ -581,12 +581,17 @@ RSpec.describe Conversation, type: :model do
|
|||
end
|
||||
|
||||
describe '#delete conversation' do
|
||||
include ActiveJob::TestHelper
|
||||
|
||||
let!(:conversation) { create(:conversation) }
|
||||
|
||||
let!(:notification) { create(:notification, notification_type: 'conversation_creation', primary_actor: conversation) }
|
||||
|
||||
it 'delete associated notifications if conversation is deleted' do
|
||||
conversation.destroy!
|
||||
perform_enqueued_jobs do
|
||||
conversation.destroy!
|
||||
end
|
||||
|
||||
expect { notification.reload }.to raise_error ActiveRecord::RecordNotFound
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Notification do
|
||||
include ActiveJob::TestHelper
|
||||
|
||||
context 'with associations' do
|
||||
it { is_expected.to belong_to(:account) }
|
||||
it { is_expected.to belong_to(:user) }
|
||||
|
@ -97,4 +99,17 @@ RSpec.describe Notification do
|
|||
})
|
||||
end
|
||||
end
|
||||
|
||||
context 'when primary actory is deleted' do
|
||||
let!(:conversation) { create(:conversation) }
|
||||
|
||||
it 'clears notifications' do
|
||||
notification = create(:notification, notification_type: 'conversation_creation', primary_actor: conversation)
|
||||
perform_enqueued_jobs do
|
||||
conversation.inbox.destroy!
|
||||
end
|
||||
|
||||
expect { notification.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue