feat: Add agent_reply_time_window in API channels (#4857)
This commit is contained in:
parent
f0db8545cb
commit
1bb0371c1d
10 changed files with 116 additions and 36 deletions
|
@ -80,7 +80,7 @@
|
|||
@click="toggleMessageSignature"
|
||||
/>
|
||||
<woot-button
|
||||
v-if="showWhatsappTemplatesButton"
|
||||
v-if="hasWhatsappTemplates"
|
||||
v-tooltip.top-end="'Whatsapp Templates'"
|
||||
icon="whatsapp"
|
||||
color-scheme="secondary"
|
||||
|
@ -275,9 +275,6 @@ export default {
|
|||
showMessageSignatureButton() {
|
||||
return !this.isPrivate && this.isAnEmailChannel;
|
||||
},
|
||||
showWhatsappTemplatesButton() {
|
||||
return !this.isOnPrivateNote && this.hasWhatsappTemplates;
|
||||
},
|
||||
sendWithSignature() {
|
||||
const { send_with_signature: isEnabled } = this.uiSettings;
|
||||
return isEnabled;
|
||||
|
|
|
@ -1,19 +1,11 @@
|
|||
<template>
|
||||
<div class="view-box fill-height">
|
||||
<banner
|
||||
v-if="!currentChat.can_reply && !isAWhatsappChannel"
|
||||
v-if="!currentChat.can_reply"
|
||||
color-scheme="alert"
|
||||
:banner-message="$t('CONVERSATION.CANNOT_REPLY')"
|
||||
:href-link="facebookReplyPolicy"
|
||||
:href-link-text="$t('CONVERSATION.24_HOURS_WINDOW')"
|
||||
/>
|
||||
|
||||
<banner
|
||||
v-if="!currentChat.can_reply && isAWhatsappChannel"
|
||||
color-scheme="alert"
|
||||
:banner-message="$t('CONVERSATION.TWILIO_WHATSAPP_CAN_REPLY')"
|
||||
:href-link="twilioWhatsAppReplyPolicy"
|
||||
:href-link-text="$t('CONVERSATION.TWILIO_WHATSAPP_24_HOURS_WINDOW')"
|
||||
:banner-message="replyWindowBannerMessage"
|
||||
:href-link="replyWindowLink"
|
||||
:href-link-text="replyWindowLinkText"
|
||||
/>
|
||||
|
||||
<banner
|
||||
|
@ -159,7 +151,6 @@ export default {
|
|||
hasSelectedTweetId() {
|
||||
return !!this.selectedTweetId;
|
||||
},
|
||||
|
||||
tweetBannerText() {
|
||||
return !this.selectedTweetId
|
||||
? this.$t('CONVERSATION.SELECT_A_TWEET_TO_REPLY')
|
||||
|
@ -237,12 +228,6 @@ export default {
|
|||
}
|
||||
return '';
|
||||
},
|
||||
facebookReplyPolicy() {
|
||||
return REPLY_POLICY.FACEBOOK;
|
||||
},
|
||||
twilioWhatsAppReplyPolicy() {
|
||||
return REPLY_POLICY.TWILIO_WHATSAPP;
|
||||
},
|
||||
isRightOrLeftIcon() {
|
||||
if (this.isContactPanelOpen) {
|
||||
return 'arrow-chevron-right';
|
||||
|
@ -254,6 +239,41 @@ export default {
|
|||
const { contact_last_seen_at: contactLastSeenAt } = this.currentChat;
|
||||
return contactLastSeenAt;
|
||||
},
|
||||
|
||||
replyWindowBannerMessage() {
|
||||
if (this.isAWhatsappChannel) {
|
||||
return this.$t('CONVERSATION.TWILIO_WHATSAPP_CAN_REPLY');
|
||||
}
|
||||
if (this.isAPIInbox) {
|
||||
const { additional_attributes: additionalAttributes = {} } = this.inbox;
|
||||
if (additionalAttributes) {
|
||||
const {
|
||||
agent_reply_time_window_message: agentReplyTimeWindowMessage,
|
||||
} = additionalAttributes;
|
||||
return agentReplyTimeWindowMessage;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
return this.$t('CONVERSATION.CANNOT_REPLY');
|
||||
},
|
||||
replyWindowLink() {
|
||||
if (this.isAWhatsappChannel) {
|
||||
return REPLY_POLICY.FACEBOOK;
|
||||
}
|
||||
if (!this.isAPIInbox) {
|
||||
return REPLY_POLICY.TWILIO_WHATSAPP;
|
||||
}
|
||||
return '';
|
||||
},
|
||||
replyWindowLinkText() {
|
||||
if (this.isAWhatsappChannel) {
|
||||
return this.$t('CONVERSATION.24_HOURS_WINDOW');
|
||||
}
|
||||
if (!this.isAPIInbox) {
|
||||
return this.$t('CONVERSATION.TWILIO_WHATSAPP_24_HOURS_WINDOW');
|
||||
}
|
||||
return '';
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
|
|
|
@ -26,8 +26,22 @@ class Channel::Api < ApplicationRecord
|
|||
|
||||
has_secure_token :identifier
|
||||
has_secure_token :hmac_token
|
||||
validate :ensure_valid_agent_reply_time_window
|
||||
|
||||
def name
|
||||
'API'
|
||||
end
|
||||
|
||||
def messaging_window_enabled?
|
||||
additional_attributes.present? && additional_attributes['agent_reply_time_window'].present?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensure_valid_agent_reply_time_window
|
||||
return if additional_attributes['agent_reply_time_window'].blank?
|
||||
return if additional_attributes['agent_reply_time_window'].to_i.positive?
|
||||
|
||||
errors.add(:agent_reply_time_window, 'agent_reply_time_window must be greater than 0')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,7 +32,7 @@ class Channel::FacebookPage < ApplicationRecord
|
|||
'Facebook'
|
||||
end
|
||||
|
||||
def has_24_hour_messaging_window?
|
||||
def messaging_window_enabled?
|
||||
false
|
||||
end
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class Channel::TwilioSms < ApplicationRecord
|
|||
medium == 'sms' ? 'Twilio SMS' : 'Whatsapp'
|
||||
end
|
||||
|
||||
def has_24_hour_messaging_window?
|
||||
def messaging_window_enabled?
|
||||
medium == 'whatsapp'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -57,7 +57,7 @@ class Channel::Whatsapp < ApplicationRecord
|
|||
{ 'D360-API-KEY' => provider_config['api_key'], 'Content-Type' => 'application/json' }
|
||||
end
|
||||
|
||||
def has_24_hour_messaging_window?
|
||||
def messaging_window_enabled?
|
||||
true
|
||||
end
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ module Channelable
|
|||
has_one :inbox, as: :channel, dependent: :destroy_async
|
||||
end
|
||||
|
||||
def has_24_hour_messaging_window?
|
||||
def messaging_window_enabled?
|
||||
false
|
||||
end
|
||||
end
|
||||
|
|
|
@ -93,23 +93,24 @@ class Conversation < ApplicationRecord
|
|||
delegate :auto_resolve_duration, to: :account
|
||||
|
||||
def can_reply?
|
||||
channel = inbox&.channel
|
||||
|
||||
return can_reply_on_instagram? if additional_attributes['type'] == 'instagram_direct_message'
|
||||
|
||||
return true unless inbox&.channel&.has_24_hour_messaging_window?
|
||||
return true unless channel&.messaging_window_enabled?
|
||||
|
||||
return false if last_incoming_message.nil?
|
||||
|
||||
last_message_less_than_24_hrs?
|
||||
messaging_window = inbox.api? ? channel.additional_attributes['agent_reply_time_window'].to_i : 24
|
||||
last_message_in_messaging_window?(messaging_window)
|
||||
end
|
||||
|
||||
def last_incoming_message
|
||||
messages&.incoming&.last
|
||||
end
|
||||
|
||||
def last_message_less_than_24_hrs?
|
||||
def last_message_in_messaging_window?(time)
|
||||
return false if last_incoming_message.nil?
|
||||
|
||||
Time.current < last_incoming_message.created_at + 24.hours
|
||||
Time.current < last_incoming_message.created_at + time.hours
|
||||
end
|
||||
|
||||
def can_reply_on_instagram?
|
||||
|
@ -120,7 +121,7 @@ class Conversation < ApplicationRecord
|
|||
if global_config['ENABLE_MESSENGER_CHANNEL_HUMAN_AGENT']
|
||||
Time.current < last_incoming_message.created_at + 7.days
|
||||
else
|
||||
last_message_less_than_24_hrs?
|
||||
last_message_in_messaging_window?(24)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ RSpec.describe Channel::TwilioSms do
|
|||
let!(:whatsapp_channel) { create(:channel_twilio_sms, medium: :whatsapp) }
|
||||
|
||||
it 'returns true' do
|
||||
expect(whatsapp_channel.has_24_hour_messaging_window?).to eq true
|
||||
expect(whatsapp_channel.messaging_window_enabled?).to eq true
|
||||
expect(whatsapp_channel.name).to eq 'Whatsapp'
|
||||
expect(whatsapp_channel.medium).to eq 'whatsapp'
|
||||
end
|
||||
|
@ -17,7 +17,7 @@ RSpec.describe Channel::TwilioSms do
|
|||
let!(:sms_channel) { create(:channel_twilio_sms, medium: :sms) }
|
||||
|
||||
it 'returns false' do
|
||||
expect(sms_channel.has_24_hour_messaging_window?).to eq false
|
||||
expect(sms_channel.messaging_window_enabled?).to eq false
|
||||
expect(sms_channel.name).to eq 'Twilio SMS'
|
||||
expect(sms_channel.medium).to eq 'sms'
|
||||
end
|
||||
|
|
|
@ -545,6 +545,54 @@ RSpec.describe Conversation, type: :model do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'on API channels' do
|
||||
let!(:api_channel) { create(:channel_api, additional_attributes: {}) }
|
||||
let!(:api_channel_with_limit) { create(:channel_api, additional_attributes: { agent_reply_time_window: '12' }) }
|
||||
|
||||
context 'when agent_reply_time_window is not configured' do
|
||||
it 'return true irrespective of the last message time' do
|
||||
conversation = create(:conversation, inbox: api_channel.inbox)
|
||||
create(
|
||||
:message,
|
||||
account: conversation.account,
|
||||
inbox: api_channel.inbox,
|
||||
conversation: conversation,
|
||||
created_at: Time.now - 13.hours
|
||||
)
|
||||
|
||||
expect(api_channel.additional_attributes['agent_reply_time_window']).to eq nil
|
||||
expect(conversation.can_reply?).to eq true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when agent_reply_time_window is configured' do
|
||||
it 'return false if it is outside of agent_reply_time_window' do
|
||||
conversation = create(:conversation, inbox: api_channel_with_limit.inbox)
|
||||
create(
|
||||
:message,
|
||||
account: conversation.account,
|
||||
inbox: api_channel_with_limit.inbox,
|
||||
conversation: conversation,
|
||||
created_at: Time.now - 13.hours
|
||||
)
|
||||
|
||||
expect(api_channel_with_limit.additional_attributes['agent_reply_time_window']).to eq '12'
|
||||
expect(conversation.can_reply?).to eq false
|
||||
end
|
||||
|
||||
it 'return true if it is inside of agent_reply_time_window' do
|
||||
conversation = create(:conversation, inbox: api_channel_with_limit.inbox)
|
||||
create(
|
||||
:message,
|
||||
account: conversation.account,
|
||||
inbox: api_channel_with_limit.inbox,
|
||||
conversation: conversation
|
||||
)
|
||||
expect(conversation.can_reply?).to eq true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#delete conversation' do
|
||||
|
|
Loading…
Reference in a new issue