diff --git a/app/controllers/public/api/v1/inboxes/conversations_controller.rb b/app/controllers/public/api/v1/inboxes/conversations_controller.rb index 129d8c8dd..3d553fee6 100644 --- a/app/controllers/public/api/v1/inboxes/conversations_controller.rb +++ b/app/controllers/public/api/v1/inboxes/conversations_controller.rb @@ -1,7 +1,7 @@ class Public::Api::V1::Inboxes::ConversationsController < Public::Api::V1::InboxesController include Events::Types before_action :set_conversation, only: [:toggle_typing, :update_last_seen, :show, :toggle_status] - before_action :ensure_inbox_active, only: [:create, :toggle_typing, :toggle_status, :update_last_seen] + before_action :ensure_inbox_active, only: [:create, :toggle_typing, :toggle_status] def index @conversations = @contact_inbox.hmac_verified? ? @contact_inbox.contact.conversations : @contact_inbox.conversations diff --git a/app/jobs/send_reply_job.rb b/app/jobs/send_reply_job.rb index 90ed2e999..f32275157 100644 --- a/app/jobs/send_reply_job.rb +++ b/app/jobs/send_reply_job.rb @@ -44,17 +44,43 @@ class SendReplyJob < ApplicationJob end def deliverable_reply?(message, channel_name) - return false if message.private? - return false unless message.outgoing? || message.template? - return false if message.source_id.present? - return false if message.content_type == 'voice_call' - return message.email_notifiable_message? if email_delivery_channel?(channel_name) + return false unless deliverable_message?(message) + return message.email_notifiable_message? if email_channel?(channel_name) + return email_notification_deliverable?(message, channel_name) if email_notification_channel?(channel_name) true end - def email_delivery_channel?(channel_name) - %w[Channel::Email Channel::WebWidget Channel::Api].include?(channel_name) + def deliverable_message?(message) + return false if message.private? + return false unless message.outgoing? || message.template? + return false if message.source_id.present? + return false if message.content_type == 'voice_call' + + true + end + + def email_channel?(channel_name) + channel_name == 'Channel::Email' + end + + def email_notification_channel?(channel_name) + %w[Channel::WebWidget Channel::Api].include?(channel_name) + end + + def email_notification_deliverable?(message, channel_name) + return false unless message.email_notifiable_message? + return false if message.conversation.contact.email.blank? + return false unless message.account.within_email_rate_limit? + + email_notification_enabled?(message.inbox, channel_name) + end + + def email_notification_enabled?(inbox, channel_name) + return inbox.channel.continuity_via_email if channel_name == 'Channel::WebWidget' + return inbox.account.feature_enabled?('email_continuity_on_api_channel') if channel_name == 'Channel::Api' + + false end def mark_message_failed(message) diff --git a/spec/controllers/public/api/v1/inbox/conversations_controller_spec.rb b/spec/controllers/public/api/v1/inbox/conversations_controller_spec.rb index 6684d18cf..75e451d7f 100644 --- a/spec/controllers/public/api/v1/inbox/conversations_controller_spec.rb +++ b/spec/controllers/public/api/v1/inbox/conversations_controller_spec.rb @@ -139,5 +139,18 @@ RSpec.describe 'Public Inbox Contact Conversations API', type: :request do expect(response).to have_http_status(:success) expect(conversation.reload.contact_last_seen_at).not_to eq contact_last_seen_at end + + it 'updates the last seen when the inbox is disabled' do + current_time = DateTime.now.utc + allow(DateTime).to receive(:now).and_return(current_time) + api_channel.inbox.update!(active: false) + + expect(Conversations::UpdateMessageStatusJob).to receive(:perform_later).with(conversation.id, current_time) + + post update_last_seen_path + + expect(response).to have_http_status(:success) + expect(conversation.reload.contact_last_seen_at).not_to be_nil + end end end diff --git a/spec/jobs/send_reply_job_spec.rb b/spec/jobs/send_reply_job_spec.rb index c1da274ae..0c796d500 100644 --- a/spec/jobs/send_reply_job_spec.rb +++ b/spec/jobs/send_reply_job_spec.rb @@ -168,5 +168,16 @@ RSpec.describe SendReplyJob do expect(message.reload).not_to be_failed expect(message.external_error).to be_nil end + + it 'does not mark web widget replies as failed when email continuity is disabled' do + webwidget_channel = create(:channel_widget, continuity_via_email: false) + message = create(:message, message_type: :outgoing, conversation: create(:conversation, inbox: webwidget_channel.inbox)) + webwidget_channel.inbox.update!(active: false) + + described_class.perform_now(message.id) + + expect(message.reload).not_to be_failed + expect(message.external_error).to be_nil + end end end