Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aef9f05b9d | ||
|
|
8c922fd8df | ||
|
|
aaf70cf1cf | ||
|
|
ec283f6657 | ||
|
|
4c6954fefc | ||
|
|
9ef93fda87 | ||
|
|
bca3d98268 | ||
|
|
95cd68813f | ||
|
|
ac85ccf2cf | ||
|
|
78a4dce5b9 | ||
|
|
28c1dd0a26 | ||
|
|
377aeb8087 | ||
|
|
117a1405e5 | ||
|
|
1f8ac8a59c | ||
|
|
78855afe8b | ||
|
|
2566155e04 | ||
|
|
ce6ae2cc47 | ||
|
|
9ecb847d9b | ||
|
|
fdffc39663 | ||
|
|
ac5aee3c8d | ||
|
|
94ede8a654 | ||
|
|
07a7c1eb8b | ||
|
|
b125ac1ad6 | ||
|
|
ecfa19bb1a | ||
|
|
733a851607 | ||
|
|
8c4b13b737 | ||
|
|
1c73aa9ef4 | ||
|
|
bafaf9c786 | ||
|
|
75dd77a92d | ||
|
|
ffbc7cb846 | ||
|
|
d88d195e73 | ||
|
|
27c51a0bdf | ||
|
|
822411d804 |
@@ -62,6 +62,7 @@ Metrics/ModuleLength:
|
||||
Exclude:
|
||||
- lib/seeders/message_seeder.rb
|
||||
- spec/support/slack_stubs.rb
|
||||
- app/mailboxes/mailbox_helper.rb
|
||||
Rails/ApplicationController:
|
||||
Exclude:
|
||||
- 'app/controllers/api/v1/widget/messages_controller.rb'
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# for contact inbox logic it uses the contact inbox builder
|
||||
|
||||
class ContactInboxWithContactBuilder
|
||||
include ContactHelper
|
||||
pattr_initialize [:inbox!, :contact_attributes!, :source_id, :hmac_verified]
|
||||
|
||||
def perform
|
||||
@@ -49,8 +50,12 @@ class ContactInboxWithContactBuilder
|
||||
end
|
||||
|
||||
def create_contact
|
||||
# TODO: Consider name as first_name and we will change the name to full_name in the future
|
||||
name, middle_name, last_name = extract_name_parts
|
||||
account.contacts.create!(
|
||||
name: contact_attributes[:name] || ::Haikunator.haikunate(1000),
|
||||
name: name,
|
||||
middle_name: middle_name,
|
||||
last_name: last_name,
|
||||
phone_number: contact_attributes[:phone_number],
|
||||
email: contact_attributes[:email],
|
||||
identifier: contact_attributes[:identifier],
|
||||
@@ -59,6 +64,20 @@ class ContactInboxWithContactBuilder
|
||||
)
|
||||
end
|
||||
|
||||
def extract_name_parts
|
||||
# Return a generated name if name attribute is blank
|
||||
return [::Haikunator.haikunate(1000), '', ''] if contact_attributes[:name].blank?
|
||||
|
||||
# Return the all name parts if middle_name or last_name is present
|
||||
if contact_attributes[:middle_name].present? || contact_attributes[:last_name].present?
|
||||
return [contact_attributes[:name], contact_attributes[:middle_name], contact_attributes[:last_name]]
|
||||
end
|
||||
|
||||
# If name is present, split it into first and last name
|
||||
name_parts = parse_name(contact_attributes[:name])
|
||||
[name_parts[:first_name], name_parts[:middle_name], name_parts[:last_name]]
|
||||
end
|
||||
|
||||
def find_contact
|
||||
contact = find_contact_by_identifier(contact_attributes[:identifier])
|
||||
contact ||= find_contact_by_email(contact_attributes[:email])
|
||||
|
||||
@@ -104,7 +104,8 @@ class Messages::Facebook::MessageBuilder < Messages::Messenger::MessageBuilder
|
||||
|
||||
def process_contact_params_result(result)
|
||||
{
|
||||
name: "#{result['first_name'] || 'John'} #{result['last_name'] || 'Doe'}",
|
||||
name: result['first_name'] || 'John',
|
||||
last_name: result['last_name'] || 'Doe',
|
||||
account_id: @inbox.account_id,
|
||||
avatar_url: result['profile_pic']
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ module ContactHelper
|
||||
end
|
||||
|
||||
def valid_number?(full_name)
|
||||
full_name.gsub(/\s+/, '').match?(/\A\+?\d+\z/)
|
||||
TelephoneNumber.parse(full_name).valid?
|
||||
end
|
||||
|
||||
def single_word_name_hash(full_name)
|
||||
|
||||
@@ -87,7 +87,10 @@
|
||||
"conversation_assignment": "Conversation Assigned",
|
||||
"assigned_conversation_new_message": "New Message",
|
||||
"participating_conversation_new_message": "New Message",
|
||||
"conversation_mention": "Mention"
|
||||
"conversation_mention": "Mention",
|
||||
"sla_missed_first_response": "SLA Missed",
|
||||
"sla_missed_next_response": "SLA Missed",
|
||||
"sla_missed_resolution": "SLA Missed"
|
||||
}
|
||||
},
|
||||
"NETWORK": {
|
||||
|
||||
@@ -22,7 +22,10 @@
|
||||
"CONVERSATION_CREATION": "New conversation created",
|
||||
"CONVERSATION_ASSIGNMENT": "A conversation has been assigned to you",
|
||||
"ASSIGNED_CONVERSATION_NEW_MESSAGE": "New message in an assigned conversation",
|
||||
"PARTICIPATING_CONVERSATION_NEW_MESSAGE": "New message in a conversation you are participating in"
|
||||
"PARTICIPATING_CONVERSATION_NEW_MESSAGE": "New message in a conversation you are participating in",
|
||||
"SLA_MISSED_FIRST_RESPONSE": "SLA target first response missed for conversation",
|
||||
"SLA_MISSED_NEXT_RESPONSE": "SLA target next response missed for conversation",
|
||||
"SLA_MISSED_RESOLUTION": "SLA target resolution missed for conversation"
|
||||
},
|
||||
"MENU_ITEM": {
|
||||
"MARK_AS_READ": "Mark as read",
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
module MailboxHelper
|
||||
include ContactHelper
|
||||
|
||||
private
|
||||
|
||||
def create_message
|
||||
@@ -96,11 +98,17 @@ module MailboxHelper
|
||||
end
|
||||
|
||||
def create_contact
|
||||
name_parts = parse_name(identify_contact_name)
|
||||
first_name = name_parts[:first_name]
|
||||
middle_name = name_parts[:middle_name]
|
||||
last_name = name_parts[:last_name]
|
||||
@contact_inbox = ::ContactInboxWithContactBuilder.new(
|
||||
source_id: processed_mail.original_sender,
|
||||
inbox: @inbox,
|
||||
contact_attributes: {
|
||||
name: identify_contact_name,
|
||||
name: first_name,
|
||||
middle_name: middle_name,
|
||||
last_name: last_name,
|
||||
email: processed_mail.original_sender,
|
||||
additional_attributes: {
|
||||
source_id: "email:#{processed_mail.message_id}"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
class Channel::FacebookPage < ApplicationRecord
|
||||
include Channelable
|
||||
include Reauthorizable
|
||||
include ContactHelper
|
||||
|
||||
self.table_name = 'channel_facebook_pages'
|
||||
|
||||
@@ -37,10 +38,14 @@ class Channel::FacebookPage < ApplicationRecord
|
||||
end
|
||||
|
||||
def create_contact_inbox(instagram_id, name)
|
||||
name_parts = parse_name(name)
|
||||
first_name = name_parts[:first_name]
|
||||
last_name = name_parts[:last_name]
|
||||
middle_name = name_parts[:middle_name]
|
||||
@contact_inbox = ::ContactInboxWithContactBuilder.new({
|
||||
source_id: instagram_id,
|
||||
inbox: inbox,
|
||||
contact_attributes: { name: name }
|
||||
contact_attributes: { name: first_name, last_name: last_name, middle_name: middle_name }
|
||||
}).perform
|
||||
end
|
||||
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
|
||||
# rubocop:enable Layout/LineLength
|
||||
|
||||
# Notes
|
||||
# TODO: We are considering the "name" as "first_name". We will update it to "first_name" in the future.
|
||||
|
||||
class Contact < ApplicationRecord
|
||||
include Avatarable
|
||||
include AvailabilityStatusable
|
||||
|
||||
+26
-12
@@ -39,7 +39,10 @@ class Notification < ApplicationRecord
|
||||
conversation_assignment: 2,
|
||||
assigned_conversation_new_message: 3,
|
||||
conversation_mention: 4,
|
||||
participating_conversation_new_message: 5
|
||||
participating_conversation_new_message: 5,
|
||||
sla_missed_first_response: 6,
|
||||
sla_missed_next_response: 7,
|
||||
sla_missed_resolution: 8
|
||||
}.freeze
|
||||
|
||||
enum notification_type: NOTIFICATION_TYPES
|
||||
@@ -86,21 +89,32 @@ class Notification < ApplicationRecord
|
||||
}
|
||||
end
|
||||
|
||||
# TODO: move to a data presenter
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
def push_message_title
|
||||
case notification_type
|
||||
when 'conversation_creation'
|
||||
I18n.t('notifications.notification_title.conversation_creation', display_id: conversation.display_id, inbox_name: primary_actor.inbox.name)
|
||||
when 'conversation_assignment'
|
||||
I18n.t('notifications.notification_title.conversation_assignment', display_id: conversation.display_id)
|
||||
when 'assigned_conversation_new_message', 'participating_conversation_new_message'
|
||||
I18n.t('notifications.notification_title.assigned_conversation_new_message', display_id: conversation.display_id)
|
||||
when 'conversation_mention'
|
||||
I18n.t('notifications.notification_title.conversation_mention', display_id: conversation.display_id)
|
||||
notification_title_map = {
|
||||
'conversation_creation' => 'notifications.notification_title.conversation_creation',
|
||||
'conversation_assignment' => 'notifications.notification_title.conversation_assignment',
|
||||
'assigned_conversation_new_message' => 'notifications.notification_title.assigned_conversation_new_message',
|
||||
'participating_conversation_new_message' => 'notifications.notification_title.assigned_conversation_new_message',
|
||||
'conversation_mention' => 'notifications.notification_title.conversation_mention',
|
||||
'sla_missed_first_response' => 'notifications.notification_title.sla_missed_first_response',
|
||||
'sla_missed_next_response' => 'notifications.notification_title.sla_missed_next_response',
|
||||
'sla_missed_resolution' => 'notifications.notification_title.sla_missed_resolution'
|
||||
}
|
||||
|
||||
i18n_key = notification_title_map[notification_type]
|
||||
return '' unless i18n_key
|
||||
|
||||
if notification_type == 'conversation_creation'
|
||||
I18n.t(i18n_key, display_id: conversation.display_id, inbox_name: primary_actor.inbox.name)
|
||||
elsif %w[conversation_assignment assigned_conversation_new_message participating_conversation_new_message
|
||||
conversation_mention].include?(notification_type)
|
||||
I18n.t(i18n_key, display_id: conversation.display_id)
|
||||
else
|
||||
''
|
||||
I18n.t(i18n_key, display_id: primary_actor.display_id)
|
||||
end
|
||||
end
|
||||
# rubocop:enable Metrics/MethodLength
|
||||
|
||||
def push_message_body
|
||||
case notification_type
|
||||
|
||||
@@ -71,7 +71,8 @@ class Telegram::IncomingMessageService
|
||||
|
||||
def contact_attributes
|
||||
{
|
||||
name: "#{telegram_params_first_name} #{telegram_params_last_name}",
|
||||
name: telegram_params_first_name,
|
||||
last_name: telegram_params_last_name,
|
||||
additional_attributes: additional_attributes
|
||||
}
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# https://developers.facebook.com/docs/whatsapp/api/media/
|
||||
class Whatsapp::IncomingMessageBaseService
|
||||
include ::Whatsapp::IncomingMessageServiceHelpers
|
||||
|
||||
include ContactHelper
|
||||
pattr_initialize [:inbox!, :params!]
|
||||
|
||||
def perform
|
||||
@@ -84,10 +84,17 @@ class Whatsapp::IncomingMessageBaseService
|
||||
|
||||
waid = processed_waid(contact_params[:wa_id])
|
||||
|
||||
name = contact_params.dig(:profile, :name)
|
||||
name_parts = parse_name(name)
|
||||
first_name = name_parts[:first_name]
|
||||
middle_name = name_parts[:middle_name]
|
||||
last_name = name_parts[:last_name]
|
||||
|
||||
contact_inbox = ::ContactInboxWithContactBuilder.new(
|
||||
source_id: waid,
|
||||
inbox: inbox,
|
||||
contact_attributes: { name: contact_params.dig(:profile, :name), phone_number: "+#{@processed_params[:messages].first[:from]}" }
|
||||
contact_attributes: { name: first_name, last_name: last_name, middle_name: middle_name,
|
||||
phone_number: "+#{@processed_params[:messages].first[:from]}" }
|
||||
).perform
|
||||
|
||||
@contact_inbox = contact_inbox
|
||||
|
||||
@@ -122,6 +122,9 @@ en:
|
||||
conversation_assignment: "A conversation (#%{display_id}) has been assigned to you"
|
||||
assigned_conversation_new_message: "A new message is created in conversation (#%{display_id})"
|
||||
conversation_mention: "You have been mentioned in conversation (#%{display_id})"
|
||||
sla_missed_first_response: "SLA target first response missed for conversation (#%{display_id})"
|
||||
sla_missed_next_response: "SLA target next response missed for conversation (#%{display_id})"
|
||||
sla_missed_resolution: "SLA target resolution missed for conversation (#%{display_id})"
|
||||
attachment: "Attachment"
|
||||
no_content: "No content"
|
||||
conversations:
|
||||
|
||||
@@ -22,4 +22,14 @@ class SlaPolicy < ApplicationRecord
|
||||
validates :name, presence: true
|
||||
|
||||
has_many :conversations, dependent: :nullify
|
||||
|
||||
def push_event_data
|
||||
{
|
||||
id: id,
|
||||
name: name,
|
||||
frt: first_response_time_threshold,
|
||||
nrt: next_response_time_threshold,
|
||||
rt: resolution_time_threshold
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -30,7 +30,7 @@ class Sla::EvaluateAppliedSlaService
|
||||
return if first_reply_was_within_threshold?(conversation, threshold)
|
||||
return if still_within_threshold?(threshold)
|
||||
|
||||
handle_missed_sla(applied_sla)
|
||||
handle_missed_sla(applied_sla, 'frt')
|
||||
end
|
||||
|
||||
def first_reply_was_within_threshold?(conversation, threshold)
|
||||
@@ -46,7 +46,7 @@ class Sla::EvaluateAppliedSlaService
|
||||
threshold = conversation.waiting_since.to_i + sla_policy.next_response_time_threshold.to_i
|
||||
return if still_within_threshold?(threshold)
|
||||
|
||||
handle_missed_sla(applied_sla)
|
||||
handle_missed_sla(applied_sla, 'nrt')
|
||||
end
|
||||
|
||||
def check_resolution_time_threshold(applied_sla, conversation, sla_policy)
|
||||
@@ -55,13 +55,14 @@ class Sla::EvaluateAppliedSlaService
|
||||
threshold = conversation.created_at.to_i + sla_policy.resolution_time_threshold.to_i
|
||||
return if still_within_threshold?(threshold)
|
||||
|
||||
handle_missed_sla(applied_sla)
|
||||
handle_missed_sla(applied_sla, 'rt')
|
||||
end
|
||||
|
||||
def handle_missed_sla(applied_sla)
|
||||
def handle_missed_sla(applied_sla, type)
|
||||
return unless applied_sla.active?
|
||||
|
||||
applied_sla.update!(sla_status: 'missed')
|
||||
generate_notifications_for_sla(applied_sla, type)
|
||||
Rails.logger.warn "SLA missed for conversation #{applied_sla.conversation.id} " \
|
||||
"in account #{applied_sla.account_id} " \
|
||||
"for sla_policy #{applied_sla.sla_policy.id}"
|
||||
@@ -75,4 +76,30 @@ class Sla::EvaluateAppliedSlaService
|
||||
"in account #{applied_sla.account_id} " \
|
||||
"for sla_policy #{applied_sla.sla_policy.id}"
|
||||
end
|
||||
|
||||
def generate_notifications_for_sla(applied_sla, type)
|
||||
notify_users = applied_sla.conversation.conversation_participants.map(&:user)
|
||||
# add all admins from the account to notify list
|
||||
notify_users += applied_sla.account.administrators
|
||||
# ensure conversation assignee is notified
|
||||
notify_users += [applied_sla.conversation.assignee] if applied_sla.conversation.assignee.present?
|
||||
|
||||
notification_type = if type == 'frt'
|
||||
'sla_missed_first_response'
|
||||
elsif type == 'nrt'
|
||||
'sla_missed_next_response'
|
||||
else
|
||||
'sla_missed_resolution'
|
||||
end
|
||||
|
||||
notify_users.uniq.each do |user|
|
||||
NotificationBuilder.new(
|
||||
notification_type: notification_type,
|
||||
user: user,
|
||||
account: applied_sla.account,
|
||||
primary_actor: applied_sla.conversation,
|
||||
secondary_actor: applied_sla.sla_policy
|
||||
).perform
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,6 +13,7 @@ describe ContactInboxWithContactBuilder do
|
||||
inbox: inbox,
|
||||
contact_attributes: {
|
||||
name: 'Contact',
|
||||
last_name: '1',
|
||||
phone_number: '+1234567890',
|
||||
email: 'testemail@example.com'
|
||||
}
|
||||
@@ -27,6 +28,7 @@ describe ContactInboxWithContactBuilder do
|
||||
inbox: inbox,
|
||||
contact_attributes: {
|
||||
name: 'Contact',
|
||||
last_name: '1',
|
||||
phone_number: '+1234567890',
|
||||
email: 'testemail@example.com',
|
||||
custom_attributes: { test: 'test' }
|
||||
@@ -35,6 +37,7 @@ describe ContactInboxWithContactBuilder do
|
||||
|
||||
expect(contact_inbox.contact.id).not_to eq(contact.id)
|
||||
expect(contact_inbox.contact.name).to eq('Contact')
|
||||
expect(contact_inbox.contact.last_name).to eq('1')
|
||||
expect(contact_inbox.contact.custom_attributes).to eq({ 'test' => 'test' })
|
||||
expect(contact_inbox.inbox_id).to eq(inbox.id)
|
||||
end
|
||||
|
||||
@@ -28,7 +28,8 @@ describe Messages::Facebook::MessageBuilder do
|
||||
contact = facebook_channel.inbox.contacts.first
|
||||
message = facebook_channel.inbox.messages.first
|
||||
|
||||
expect(contact.name).to eq('Jane Dae')
|
||||
expect(contact.name).to eq('Jane')
|
||||
expect(contact.last_name).to eq('Dae')
|
||||
expect(message.content).to eq('facebook message')
|
||||
end
|
||||
|
||||
@@ -53,10 +54,11 @@ describe Messages::Facebook::MessageBuilder do
|
||||
|
||||
contact = facebook_channel.inbox.contacts.first
|
||||
# Refer: https://github.com/chatwoot/chatwoot/pull/3016 for this check
|
||||
default_name = 'John Doe'
|
||||
default_name = 'John'
|
||||
|
||||
expect(facebook_channel.inbox.reload.contacts.count).to eq(1)
|
||||
expect(contact.name).to eq(default_name)
|
||||
expect(contact.last_name).to eq('Doe')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Sla::EvaluateAppliedSlaService do
|
||||
let!(:conversation) { create(:conversation, created_at: 6.hours.ago) }
|
||||
let!(:account) { create(:account) }
|
||||
let!(:user_1) { create(:user, account: account) }
|
||||
let!(:user_2) { create(:user, account: account) }
|
||||
let!(:admin) { create(:user, account: account, role: :administrator) }
|
||||
let!(:conversation) { create(:conversation, created_at: 6.hours.ago, assignee: user_1, account: account) }
|
||||
let!(:sla_policy) do
|
||||
create(:sla_policy, account: conversation.account,
|
||||
first_response_time_threshold: nil,
|
||||
@@ -20,6 +24,16 @@ RSpec.describe Sla::EvaluateAppliedSlaService do
|
||||
expect(Rails.logger).to have_received(:warn).with("SLA missed for conversation #{conversation.id} in account " \
|
||||
"#{applied_sla.account_id} for sla_policy #{sla_policy.id}")
|
||||
expect(applied_sla.reload.sla_status).to eq('missed')
|
||||
|
||||
expect(Notification.count).to eq(2)
|
||||
# check if notification type is sla_missed_first_response
|
||||
expect(Notification.where(notification_type: 'sla_missed_first_response').count).to eq(2)
|
||||
# Check if notification is created for the assignee
|
||||
expect(Notification.where(user_id: user_1.id).count).to eq(1)
|
||||
# Check if notification is created for the account admin
|
||||
expect(Notification.where(user_id: admin.id).count).to eq(1)
|
||||
# Check if no notification is created for other user
|
||||
expect(Notification.where(user_id: user_2.id).count).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -35,6 +49,16 @@ RSpec.describe Sla::EvaluateAppliedSlaService do
|
||||
expect(Rails.logger).to have_received(:warn).with("SLA missed for conversation #{conversation.id} in account " \
|
||||
"#{applied_sla.account_id} for sla_policy #{sla_policy.id}")
|
||||
expect(applied_sla.reload.sla_status).to eq('missed')
|
||||
|
||||
expect(Notification.count).to eq(2)
|
||||
# check if notification type is sla_missed_first_response
|
||||
expect(Notification.where(notification_type: 'sla_missed_next_response').count).to eq(2)
|
||||
# Check if notification is created for the assignee
|
||||
expect(Notification.where(user_id: user_1.id).count).to eq(1)
|
||||
# Check if notification is created for the account admin
|
||||
expect(Notification.where(user_id: admin.id).count).to eq(1)
|
||||
# Check if no notification is created for other user
|
||||
expect(Notification.where(user_id: user_2.id).count).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -47,6 +71,15 @@ RSpec.describe Sla::EvaluateAppliedSlaService do
|
||||
expect(Rails.logger).to have_received(:warn).with("SLA missed for conversation #{conversation.id} in account " \
|
||||
"#{applied_sla.account_id} for sla_policy #{sla_policy.id}")
|
||||
expect(applied_sla.reload.sla_status).to eq('missed')
|
||||
|
||||
expect(Notification.count).to eq(2)
|
||||
expect(Notification.where(notification_type: 'sla_missed_resolution').count).to eq(2)
|
||||
# Check if notification is created for the assignee
|
||||
expect(Notification.where(user_id: user_1.id).count).to eq(1)
|
||||
# Check if notification is created for the account admin
|
||||
expect(Notification.where(user_id: admin.id).count).to eq(1)
|
||||
# Check if no notification is created for other user
|
||||
expect(Notification.where(user_id: user_2.id).count).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -76,6 +109,7 @@ RSpec.describe Sla::EvaluateAppliedSlaService do
|
||||
expect(Rails.logger).to have_received(:warn).with("SLA missed for conversation #{conversation.id} in account " \
|
||||
"#{applied_sla.account_id} for sla_policy #{sla_policy.id}").exactly(1).time
|
||||
expect(applied_sla.reload.sla_status).to eq('missed')
|
||||
expect(Notification.count).to eq(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -99,6 +133,7 @@ RSpec.describe Sla::EvaluateAppliedSlaService do
|
||||
expect(Rails.logger).to have_received(:info).with("SLA hit for conversation #{conversation.id} in account " \
|
||||
"#{applied_sla.account_id} for sla_policy #{sla_policy.id}")
|
||||
expect(applied_sla.reload.sla_status).to eq('hit')
|
||||
expect(Notification.count).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -63,8 +63,8 @@ RSpec.describe ContactHelper do
|
||||
end
|
||||
|
||||
it 'handle name with mobile number with spaces correctly' do
|
||||
full_name = '+1 234 567 890'
|
||||
expected_result = { first_name: '+1 234 567 890', last_name: nil, middle_name: nil, prefix: nil, suffix: nil }
|
||||
full_name = '+1 423-423-4234'
|
||||
expected_result = { first_name: '+1 423-423-4234', last_name: nil, middle_name: nil, prefix: nil, suffix: nil }
|
||||
expect(helper.parse_name(full_name)).to eq(expected_result)
|
||||
end
|
||||
|
||||
|
||||
@@ -89,9 +89,9 @@ RSpec.describe SupportMailbox do
|
||||
end
|
||||
|
||||
it 'create a new contact as the sender of the email' do
|
||||
email_sender = Mail::Address.new(support_mail.mail[:from].value).name
|
||||
expect(conversation.messages.last.sender.email).to eq(support_mail.mail.from.first)
|
||||
expect(conversation.contact.name).to eq(email_sender)
|
||||
expect(conversation.contact.name).to eq('Sony')
|
||||
expect(conversation.contact.last_name).to eq('Mathew')
|
||||
end
|
||||
|
||||
it 'add the mail content as new message on the conversation' do
|
||||
@@ -178,10 +178,9 @@ RSpec.describe SupportMailbox do
|
||||
|
||||
it 'create new contact with original sender' do
|
||||
described_subject
|
||||
email_sender = Mail::Address.new(group_sender_support_mail.mail[:from].value).name
|
||||
|
||||
expect(conversation.contact.email).to eq(group_sender_support_mail.mail['X-Original-Sender'].value)
|
||||
expect(conversation.contact.name).to eq(email_sender)
|
||||
expect(conversation.contact.name).to eq('ACME')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@ describe Line::IncomingMessageService do
|
||||
)
|
||||
described_class.new(inbox: line_channel.inbox, params: params).perform
|
||||
expect(line_channel.inbox.conversations).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('LINE Test')
|
||||
expect(Contact.all.first.name).to eq('LINE')
|
||||
expect(Contact.all.first.additional_attributes['social_line_user_id']).to eq('U4af4980629')
|
||||
expect(line_channel.inbox.messages.first.content).to eq('Hello, world')
|
||||
end
|
||||
@@ -177,7 +177,7 @@ describe Line::IncomingMessageService do
|
||||
)
|
||||
described_class.new(inbox: line_channel.inbox, params: sticker_params).perform
|
||||
expect(line_channel.inbox.conversations).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('LINE Test')
|
||||
expect(Contact.all.first.name).to eq('LINE')
|
||||
expect(line_channel.inbox.messages.first.content).to eq('')
|
||||
end
|
||||
end
|
||||
@@ -204,7 +204,7 @@ describe Line::IncomingMessageService do
|
||||
)
|
||||
described_class.new(inbox: line_channel.inbox, params: image_params).perform
|
||||
expect(line_channel.inbox.conversations).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('LINE Test')
|
||||
expect(Contact.all.first.name).to eq('LINE')
|
||||
expect(Contact.all.first.additional_attributes['social_line_user_id']).to eq('U4af4980629')
|
||||
expect(line_channel.inbox.messages.first.content).to be_nil
|
||||
expect(line_channel.inbox.messages.first.attachments.first.file_type).to eq('image')
|
||||
@@ -234,7 +234,7 @@ describe Line::IncomingMessageService do
|
||||
)
|
||||
described_class.new(inbox: line_channel.inbox, params: video_params).perform
|
||||
expect(line_channel.inbox.conversations).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('LINE Test')
|
||||
expect(Contact.all.first.name).to eq('LINE')
|
||||
expect(Contact.all.first.additional_attributes['social_line_user_id']).to eq('U4af4980629')
|
||||
expect(line_channel.inbox.messages.first.content).to be_nil
|
||||
expect(line_channel.inbox.messages.first.attachments.first.file_type).to eq('video')
|
||||
|
||||
@@ -51,7 +51,8 @@ describe Telegram::IncomingMessageService do
|
||||
}.with_indifferent_access
|
||||
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
||||
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(Contact.all.first.last_name).to eq('Jose')
|
||||
expect(telegram_channel.inbox.messages.first.content).to eq('test')
|
||||
end
|
||||
end
|
||||
@@ -64,7 +65,8 @@ describe Telegram::IncomingMessageService do
|
||||
}.with_indifferent_access
|
||||
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
||||
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(Contact.all.first.last_name).to eq('Jose')
|
||||
expect(Contact.all.first.additional_attributes['social_telegram_user_id']).to eq(23)
|
||||
expect(Contact.all.first.additional_attributes['social_telegram_user_name']).to eq('sojan')
|
||||
expect(telegram_channel.inbox.messages.first.content).to eq('test')
|
||||
@@ -106,7 +108,7 @@ describe Telegram::IncomingMessageService do
|
||||
}.with_indifferent_access
|
||||
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
||||
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(Contact.all.first.additional_attributes['social_telegram_user_id']).to eq(23)
|
||||
expect(Contact.all.first.additional_attributes['social_telegram_user_name']).to eq('sojan')
|
||||
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('audio')
|
||||
@@ -127,7 +129,7 @@ describe Telegram::IncomingMessageService do
|
||||
}.with_indifferent_access
|
||||
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
||||
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('image')
|
||||
end
|
||||
end
|
||||
@@ -152,7 +154,7 @@ describe Telegram::IncomingMessageService do
|
||||
}.with_indifferent_access
|
||||
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
||||
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('image')
|
||||
end
|
||||
end
|
||||
@@ -174,7 +176,7 @@ describe Telegram::IncomingMessageService do
|
||||
}.with_indifferent_access
|
||||
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
||||
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('video')
|
||||
end
|
||||
end
|
||||
@@ -193,7 +195,7 @@ describe Telegram::IncomingMessageService do
|
||||
}.with_indifferent_access
|
||||
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
||||
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('audio')
|
||||
end
|
||||
end
|
||||
@@ -214,7 +216,7 @@ describe Telegram::IncomingMessageService do
|
||||
}.with_indifferent_access
|
||||
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
||||
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('file')
|
||||
end
|
||||
end
|
||||
@@ -252,7 +254,7 @@ describe Telegram::IncomingMessageService do
|
||||
}.with_indifferent_access
|
||||
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
||||
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('location')
|
||||
end
|
||||
end
|
||||
@@ -280,7 +282,8 @@ describe Telegram::IncomingMessageService do
|
||||
|
||||
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
||||
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(Contact.all.first.last_name).to eq('Jose')
|
||||
expect(Contact.all.first.additional_attributes['social_telegram_user_id']).to eq(5_171_248)
|
||||
expect(telegram_channel.inbox.messages.first.content).to eq('Option 1')
|
||||
end
|
||||
|
||||
@@ -20,7 +20,8 @@ describe Whatsapp::IncomingMessageService do
|
||||
it 'creates appropriate conversations, message and contacts' do
|
||||
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
||||
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(Contact.all.first.last_name).to eq('Jose')
|
||||
expect(whatsapp_channel.inbox.messages.first.content).to eq('Test')
|
||||
end
|
||||
|
||||
@@ -178,7 +179,7 @@ describe Whatsapp::IncomingMessageService do
|
||||
}.with_indifferent_access
|
||||
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
||||
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(whatsapp_channel.inbox.messages.first.content).to eq('First Button')
|
||||
end
|
||||
end
|
||||
@@ -196,7 +197,7 @@ describe Whatsapp::IncomingMessageService do
|
||||
}.with_indifferent_access
|
||||
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
||||
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(whatsapp_channel.inbox.messages.first.content).to eq('Yes this is a button')
|
||||
end
|
||||
end
|
||||
@@ -219,7 +220,7 @@ describe Whatsapp::IncomingMessageService do
|
||||
}.with_indifferent_access
|
||||
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
||||
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(whatsapp_channel.inbox.messages.first.content).to eq('Check out my product!')
|
||||
expect(whatsapp_channel.inbox.messages.first.attachments.present?).to be true
|
||||
end
|
||||
@@ -240,7 +241,7 @@ describe Whatsapp::IncomingMessageService do
|
||||
}.with_indifferent_access
|
||||
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
||||
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
location_attachment = whatsapp_channel.inbox.messages.first.attachments.first
|
||||
expect(location_attachment.file_type).to eq('location')
|
||||
expect(location_attachment.fallback_title).to eq('Bay Bridge, San Francisco, CA, USA')
|
||||
@@ -290,7 +291,8 @@ describe Whatsapp::IncomingMessageService do
|
||||
it 'creates appropriate conversations, message and contacts if contact does not exit' do
|
||||
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
||||
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(Contact.all.first.last_name).to eq('Jose')
|
||||
expect(whatsapp_channel.inbox.messages.first.content).to eq('Test')
|
||||
expect(whatsapp_channel.inbox.contact_inboxes.first.source_id).to eq(wa_id)
|
||||
end
|
||||
@@ -337,7 +339,7 @@ describe Whatsapp::IncomingMessageService do
|
||||
it 'creates contact inbox with the incoming waid' do
|
||||
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
||||
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(whatsapp_channel.inbox.messages.first.content).to eq('Test')
|
||||
expect(whatsapp_channel.inbox.contact_inboxes.first.source_id).to eq(wa_id)
|
||||
end
|
||||
|
||||
@@ -48,7 +48,8 @@ describe Whatsapp::IncomingMessageWhatsappCloudService do
|
||||
|
||||
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
||||
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(Contact.all.first.last_name).to eq('Jose')
|
||||
expect(whatsapp_channel.inbox.messages.first.content).to eq('Check out my product!')
|
||||
expect(whatsapp_channel.inbox.messages.first.attachments.present?).to be true
|
||||
end
|
||||
@@ -60,7 +61,7 @@ describe Whatsapp::IncomingMessageWhatsappCloudService do
|
||||
|
||||
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
||||
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(whatsapp_channel.inbox.messages.first.content).to eq('Check out my product!')
|
||||
expect(whatsapp_channel.inbox.messages.first.attachments.present?).to be false
|
||||
expect(whatsapp_channel.authorization_error_count).to eq(1)
|
||||
@@ -100,7 +101,7 @@ describe Whatsapp::IncomingMessageWhatsappCloudService do
|
||||
it 'with attachment errors' do
|
||||
described_class.new(inbox: whatsapp_channel.inbox, params: error_params).perform
|
||||
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
||||
expect(Contact.all.first.name).to eq('Sojan Jose')
|
||||
expect(Contact.all.first.name).to eq('Sojan')
|
||||
expect(whatsapp_channel.inbox.messages.count).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user