Compare commits

...
Author SHA1 Message Date
Pranav 3c69ddb7f4 feat: Add an activity message in conversations if source_id changes 2025-03-20 13:14:23 -07:00
4 changed files with 167 additions and 0 deletions
@@ -0,0 +1,38 @@
class ContactInbox::SourceChangeActivityJob < ApplicationJob
queue_as :default
def perform(contact_inbox_id, previous_source_id, current_source_id)
contact_inbox = ContactInbox.find_by(id: contact_inbox_id)
return if contact_inbox.blank?
activity_message = I18n.t(
activity_message_i18n_key(contact_inbox),
previous: previous_source_id,
current: current_source_id
)
contact_inbox.conversations.find_each(batch_size: 100) do |conversation|
Conversations::ActivityMessageJob.perform_later(
conversation,
account_id: conversation.account_id,
inbox_id: conversation.inbox_id,
message: activity_message,
message_type: :activity
)
end
end
private
def activity_message_i18n_key(contact_inbox)
type = if contact_inbox.inbox.email?
:email_changed
elsif contact_inbox.inbox.whatsapp?
:phone_number_changed
else
:identifier_changed
end
"contact_inboxes.source_change.#{type}"
end
end
+6
View File
@@ -31,6 +31,8 @@ class ContactInbox < ApplicationRecord
belongs_to :contact
belongs_to :inbox
after_update_commit :create_source_change_activity, if: :source_id_changed?
has_many :conversations, dependent: :destroy_async
# contact_inboxes that are not associated with any conversation
@@ -57,6 +59,10 @@ class ContactInbox < ApplicationRecord
private
def create_source_change_activity
ContactInbox::SourceChangeActivityJob.perform_later(id, source_id_was, source_id)
end
def validate_twilio_source_id
# https://www.twilio.com/docs/glossary/what-e164#regex-matching-for-e164
if inbox.channel.medium == 'sms' && !TWILIO_CHANNEL_SMS_REGEX.match?(source_id)
+5
View File
@@ -30,6 +30,11 @@
# available at https://guides.rubyonrails.org/i18n.html.
en:
contact_inboxes:
source_change:
email_changed: 'Email changed from %{previous} to %{current}'
phone_number_changed: 'Phone number changed from %{previous} to %{current}'
identifier_changed: 'Source identifier changed from %{previous} to %{current}'
hello: 'Hello world'
messages:
reset_password_success: Woot! Request for password reset is successful. Check your mail for instructions.
@@ -0,0 +1,118 @@
require 'rails_helper'
RSpec.describe ContactInbox::SourceChangeActivityJob do
let(:account) { create(:account) }
let(:contact) { create(:contact, account: account) }
let(:previous_source_id) { 'old_id' }
let(:current_source_id) { 'new_id' }
describe '#perform' do
context 'when inbox is email' do
let(:channel) { create(:channel_email, account: account) }
let(:contact_inbox) { create(:contact_inbox, contact: contact, inbox: channel.inbox) }
let(:conversation) { create(:conversation, contact: contact, inbox: channel.inbox, account: account, contact_inbox: contact_inbox) }
it 'creates activity message with email change text' do
expected_message = I18n.t(
'contact_inboxes.source_change.email_changed',
previous: previous_source_id,
current: current_source_id
)
expect(Conversations::ActivityMessageJob).to receive(:perform_later).with(
conversation,
account_id: account.id,
inbox_id: channel.inbox.id,
message: expected_message,
message_type: :activity
)
described_class.perform_now(contact_inbox.id, previous_source_id, current_source_id)
end
end
context 'when inbox is whatsapp' do
let(:channel) { create(:channel_whatsapp, account: account, sync_templates: false, validate_provider_config: false) }
let(:contact_inbox) { create(:contact_inbox, contact: contact, inbox: channel.inbox) }
let(:conversation) { create(:conversation, contact: contact, inbox: channel.inbox, account: account, contact_inbox: contact_inbox) }
it 'creates activity message with phone number change text' do
expected_message = I18n.t('contact_inboxes.source_change.phone_number_changed',
previous: previous_source_id,
current: current_source_id)
expect(Conversations::ActivityMessageJob).to receive(:perform_later).with(
conversation,
account_id: account.id,
inbox_id: channel.inbox.id,
message: expected_message,
message_type: :activity
)
described_class.perform_now(contact_inbox.id, previous_source_id, current_source_id)
end
end
context 'when inbox is of other type' do
let(:channel) { create(:channel_api, account: account) }
let(:contact_inbox) { create(:contact_inbox, contact: contact, inbox: channel.inbox) }
let(:conversation) { create(:conversation, contact: contact, inbox: channel.inbox, account: account, contact_inbox: contact_inbox) }
it 'creates activity message with generic identifier change text' do
expected_message = I18n.t('contact_inboxes.source_change.identifier_changed',
previous: previous_source_id,
current: current_source_id)
expect(Conversations::ActivityMessageJob).to receive(:perform_later).with(
conversation,
account_id: account.id,
inbox_id: channel.inbox.id,
message: expected_message,
message_type: :activity
)
described_class.perform_now(contact_inbox.id, previous_source_id, current_source_id)
end
end
context 'when multiple conversations exist' do
let(:channel) { create(:channel_whatsapp, account: account, sync_templates: false, validate_provider_config: false) }
let(:contact_inbox) { create(:contact_inbox, contact: contact, inbox: channel.inbox) }
let(:conversation) { create(:conversation, contact: contact, inbox: channel.inbox, account: account, contact_inbox: contact_inbox) }
let(:conversation2) { create(:conversation, contact: contact, inbox: channel.inbox, account: account, contact_inbox: contact_inbox) }
let(:conversation3) { create(:conversation, contact: contact, inbox: channel.inbox, account: account) }
it 'creates activity message for each conversation' do
expected_message = I18n.t('contact_inboxes.source_change.phone_number_changed',
previous: previous_source_id,
current: current_source_id)
expect(Conversations::ActivityMessageJob).to receive(:perform_later).with(
conversation,
account_id: account.id,
inbox_id: channel.inbox.id,
message: expected_message,
message_type: :activity
)
expect(Conversations::ActivityMessageJob).to receive(:perform_later).with(
conversation2,
account_id: account.id,
inbox_id: channel.inbox.id,
message: expected_message,
message_type: :activity
)
expect(Conversations::ActivityMessageJob).not_to receive(:perform_later).with(
conversation3,
account_id: account.id,
inbox_id: channel.inbox.id,
message: expected_message,
message_type: :activity
)
described_class.perform_now(contact_inbox.id, previous_source_id, current_source_id)
end
end
end
end