Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
652fee75d1 | ||
|
|
5d2ab0e017 | ||
|
|
6a07efb461 |
@@ -25,6 +25,7 @@ class Seeders::AccountSeeder
|
||||
seed_canned_responses
|
||||
seed_inboxes
|
||||
seed_contacts
|
||||
seed_csat_responses
|
||||
end
|
||||
|
||||
def set_up_account
|
||||
@@ -116,43 +117,17 @@ class Seeders::AccountSeeder
|
||||
contact.update!(contact_data.slice('name', 'email'))
|
||||
Avatar::AvatarFromUrlJob.perform_later(contact, "https://xsgames.co/randomusers/avatar.php?g=#{contact_data['gender']}")
|
||||
end
|
||||
contact_data['conversations'].each do |conversation_data|
|
||||
inbox = @account.inboxes.find_by(channel_type: conversation_data['channel'])
|
||||
contact_inbox = inbox.contact_inboxes.create_or_find_by!(contact: contact, source_id: (conversation_data['source_id'] || SecureRandom.hex))
|
||||
create_conversation(contact_inbox: contact_inbox, conversation_data: conversation_data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_conversation(contact_inbox:, conversation_data:)
|
||||
assignee = User.from_email(conversation_data['assignee']) if conversation_data['assignee'].present?
|
||||
conversation = contact_inbox.conversations.create!(account: contact_inbox.inbox.account, contact: contact_inbox.contact,
|
||||
inbox: contact_inbox.inbox, assignee: assignee)
|
||||
create_messages(conversation: conversation, messages: conversation_data['messages'])
|
||||
conversation.update_labels(conversation_data[:labels]) if conversation_data[:labels].present?
|
||||
conversation.update!(priority: conversation_data[:priority]) if conversation_data[:priority].present?
|
||||
end
|
||||
|
||||
def create_messages(conversation:, messages:)
|
||||
messages.each do |message_data|
|
||||
sender = find_message_sender(conversation, message_data)
|
||||
conversation.messages.create!(
|
||||
message_data.slice('content', 'message_type').merge(
|
||||
account: conversation.inbox.account, sender: sender, inbox: conversation.inbox
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def find_message_sender(conversation, message_data)
|
||||
if message_data['message_type'] == 'incoming'
|
||||
conversation.contact
|
||||
elsif message_data['sender'].present?
|
||||
User.from_email(message_data['sender'])
|
||||
end
|
||||
# Create conversations after all contacts are created
|
||||
Seeders::ConversationSeeder.new(account: @account, contact_data: @account_data['contacts']).perform!
|
||||
end
|
||||
|
||||
def seed_inboxes
|
||||
Seeders::InboxSeeder.new(account: @account, company_data: @account_data[:company]).perform!
|
||||
end
|
||||
|
||||
def seed_csat_responses
|
||||
Seeders::CsatSeeder.new(account: @account).perform!
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
## Class to generate sample conversations for a chatwoot test @Account.
|
||||
############################################################
|
||||
### Usage #####
|
||||
#
|
||||
# # Seed an account with conversations
|
||||
# Seeders::ConversationSeeder.new(account: Account.find(1), contact_data: []).perform!
|
||||
#
|
||||
#
|
||||
############################################################
|
||||
|
||||
class Seeders::ConversationSeeder
|
||||
def initialize(account:, contact_data:)
|
||||
raise 'Conversation Seeding is not allowed in production.' unless ENV.fetch('ENABLE_ACCOUNT_SEEDING', !Rails.env.production?)
|
||||
|
||||
@account = account
|
||||
@contact_data = contact_data
|
||||
end
|
||||
|
||||
def perform!
|
||||
seed_conversations
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def seed_conversations
|
||||
@contact_data.each do |contact_data|
|
||||
contact = @account.contacts.find_by(email: contact_data['email'])
|
||||
next unless contact
|
||||
|
||||
contact_data['conversations'].each do |conversation_data|
|
||||
inbox = @account.inboxes.find_by(channel_type: conversation_data['channel'])
|
||||
contact_inbox = inbox.contact_inboxes.create_or_find_by!(
|
||||
contact: contact,
|
||||
source_id: (conversation_data['source_id'] || SecureRandom.hex)
|
||||
)
|
||||
create_conversation(contact_inbox: contact_inbox, conversation_data: conversation_data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_conversation(contact_inbox:, conversation_data:)
|
||||
assignee = determine_assignee(conversation_data, contact_inbox.inbox)
|
||||
conversation = build_conversation(contact_inbox, assignee)
|
||||
|
||||
create_messages(conversation: conversation, messages: conversation_data['messages'])
|
||||
apply_conversation_attributes(conversation, conversation_data)
|
||||
resolve_conversation_if_needed(conversation, assignee)
|
||||
end
|
||||
|
||||
def determine_assignee(conversation_data, inbox)
|
||||
assignee = User.from_email(conversation_data['assignee']) if conversation_data['assignee'].present?
|
||||
assignee ||= @account.agents.sample if inbox.csat_survey_enabled
|
||||
assignee
|
||||
end
|
||||
|
||||
def build_conversation(contact_inbox, assignee)
|
||||
contact_inbox.conversations.create!(
|
||||
account: contact_inbox.inbox.account,
|
||||
contact: contact_inbox.contact,
|
||||
inbox: contact_inbox.inbox,
|
||||
assignee: assignee
|
||||
)
|
||||
end
|
||||
|
||||
def apply_conversation_attributes(conversation, conversation_data)
|
||||
conversation.update_labels(conversation_data[:labels]) if conversation_data[:labels].present?
|
||||
conversation.update!(priority: conversation_data[:priority]) if conversation_data[:priority].present?
|
||||
end
|
||||
|
||||
def resolve_conversation_if_needed(conversation, assignee)
|
||||
return unless assignee.present? && rand > 0.4
|
||||
|
||||
conversation.update!(status: :resolved)
|
||||
end
|
||||
|
||||
def create_messages(conversation:, messages:)
|
||||
messages.each do |message_data|
|
||||
sender = find_message_sender(conversation, message_data)
|
||||
conversation.messages.create!(
|
||||
message_data.slice('content', 'message_type').merge(
|
||||
account: conversation.inbox.account, sender: sender, inbox: conversation.inbox
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def find_message_sender(conversation, message_data)
|
||||
if message_data['message_type'] == 'incoming'
|
||||
conversation.contact
|
||||
elsif message_data['sender'].present?
|
||||
User.from_email(message_data['sender'])
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,88 @@
|
||||
## Class to generate sample CSAT survey responses for a chatwoot test @Account.
|
||||
############################################################
|
||||
### Usage #####
|
||||
#
|
||||
# # Seed an account with CSAT responses
|
||||
# Seeders::CsatSeeder.new(account: Account.find(1)).perform!
|
||||
#
|
||||
#
|
||||
############################################################
|
||||
|
||||
class Seeders::CsatSeeder
|
||||
def initialize(account:)
|
||||
raise 'CSAT Seeding is not allowed in production.' unless ENV.fetch('ENABLE_ACCOUNT_SEEDING', !Rails.env.production?)
|
||||
|
||||
@account = account
|
||||
end
|
||||
|
||||
def perform!
|
||||
seed_csat_responses
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def seed_csat_responses
|
||||
resolved_conversations = @account.conversations.where(status: :resolved)
|
||||
csat_enabled_inboxes = @account.inboxes.where(csat_survey_enabled: true)
|
||||
|
||||
return if resolved_conversations.empty? || csat_enabled_inboxes.empty?
|
||||
|
||||
# Create CSAT responses for resolved conversations in CSAT-enabled inboxes
|
||||
resolved_conversations.joins(:inbox).where(inbox: csat_enabled_inboxes).find_each do |conversation|
|
||||
# Only create CSAT for about 70% of resolved conversations to simulate real-world scenarios
|
||||
next if rand > 0.7
|
||||
|
||||
# Get the last outgoing message to attach CSAT to
|
||||
last_outgoing_message = conversation.messages.where(message_type: :outgoing).last
|
||||
next unless last_outgoing_message
|
||||
|
||||
# Create CSAT survey response with varied ratings and feedback
|
||||
create_csat_response(conversation, last_outgoing_message)
|
||||
end
|
||||
end
|
||||
|
||||
def create_csat_response(conversation, message)
|
||||
# Generate realistic rating distribution (more positive ratings)
|
||||
rating = case rand
|
||||
when 0.0..0.05 then 1 # 5%
|
||||
when 0.05..0.15 then 2 # 10%
|
||||
when 0.15..0.35 then 3 # 20%
|
||||
when 0.35..0.65 then 4 # 30%
|
||||
else 5 # 35%
|
||||
end
|
||||
|
||||
feedback_messages = [
|
||||
'Great service, very helpful!',
|
||||
'Quick response and resolved my issue',
|
||||
'Professional and courteous support',
|
||||
'Could be faster but overall good',
|
||||
'Satisfied with the resolution',
|
||||
'Excellent customer service',
|
||||
'Very knowledgeable agent',
|
||||
'Resolved quickly, thank you!',
|
||||
'Good experience overall',
|
||||
'Agent was very patient and helpful',
|
||||
'Really appreciate the help',
|
||||
'Fast and efficient service',
|
||||
'Agent went above and beyond',
|
||||
'Clear explanations provided',
|
||||
'Issue resolved on first contact',
|
||||
'', # Some responses have no feedback
|
||||
'',
|
||||
''
|
||||
]
|
||||
|
||||
CsatSurveyResponse.create!(
|
||||
account: @account,
|
||||
conversation: conversation,
|
||||
contact: conversation.contact,
|
||||
message: message,
|
||||
assigned_agent: conversation.assignee,
|
||||
rating: rating,
|
||||
feedback_message: feedback_messages.sample,
|
||||
created_at: message.created_at + rand(5..30).minutes
|
||||
)
|
||||
rescue StandardError => e
|
||||
Rails.logger.debug { "Failed to create CSAT response: #{e.message}" }
|
||||
end
|
||||
end
|
||||
@@ -30,13 +30,31 @@ class Seeders::InboxSeeder
|
||||
|
||||
def seed_website_inbox
|
||||
channel = Channel::WebWidget.create!(account: @account, website_url: "https://#{@company_data['domain']}")
|
||||
Inbox.create!(channel: channel, account: @account, name: "#{@company_data['name']} Website")
|
||||
Inbox.create!(
|
||||
channel: channel,
|
||||
account: @account,
|
||||
name: "#{@company_data['name']} Website",
|
||||
csat_survey_enabled: true,
|
||||
csat_config: {
|
||||
'display_type' => 'emoji',
|
||||
'message' => 'How would you rate your experience?'
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
def seed_facebook_inbox
|
||||
channel = Channel::FacebookPage.create!(account: @account, user_access_token: SecureRandom.hex, page_access_token: SecureRandom.hex,
|
||||
page_id: SecureRandom.hex)
|
||||
Inbox.create!(channel: channel, account: @account, name: "#{@company_data['name']} Facebook")
|
||||
Inbox.create!(
|
||||
channel: channel,
|
||||
account: @account,
|
||||
name: "#{@company_data['name']} Facebook",
|
||||
csat_survey_enabled: true,
|
||||
csat_config: {
|
||||
'display_type' => 'star',
|
||||
'message' => 'Please rate your support experience'
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
def seed_twitter_inbox
|
||||
@@ -71,7 +89,16 @@ class Seeders::InboxSeeder
|
||||
def seed_email_inbox
|
||||
channel = Channel::Email.create!(account: @account, email: "test#{SecureRandom.hex}@#{@company_data['domain']}",
|
||||
forward_to_email: "test_fwd#{SecureRandom.hex}@#{@company_data['domain']}")
|
||||
Inbox.create!(channel: channel, account: @account, name: "#{@company_data['name']} Email")
|
||||
Inbox.create!(
|
||||
channel: channel,
|
||||
account: @account,
|
||||
name: "#{@company_data['name']} Email",
|
||||
csat_survey_enabled: true,
|
||||
csat_config: {
|
||||
'display_type' => 'emoji',
|
||||
'message' => 'How was your support experience today?'
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
def seed_api_inbox
|
||||
|
||||
@@ -477,4 +477,55 @@ contacts:
|
||||
- message_type: outgoing
|
||||
sender: michael_scott@paperlayer.test
|
||||
content: How may i help you ?
|
||||
sender: michael_scott@paperlayer.test
|
||||
- name: "Robert Maxwell"
|
||||
email: "rmaxwell@example.test"
|
||||
gender: 'male'
|
||||
conversations:
|
||||
- channel: Channel::WebWidget
|
||||
assignee: karn@paperlayer.test
|
||||
messages:
|
||||
- message_type: incoming
|
||||
content: "Hi, I need help with my account settings."
|
||||
- message_type: outgoing
|
||||
sender: karn@paperlayer.test
|
||||
content: "I'd be happy to help you with your account settings. What specifically would you like to change?"
|
||||
- message_type: incoming
|
||||
content: "I want to update my billing information."
|
||||
- message_type: outgoing
|
||||
sender: karn@paperlayer.test
|
||||
content: "Perfect! I've sent you a secure link to update your billing information. Please check your email."
|
||||
- name: "Sarah Johnson"
|
||||
email: "sjohnson@demo.test"
|
||||
gender: 'female'
|
||||
conversations:
|
||||
- channel: Channel::FacebookPage
|
||||
assignee: danny@paperlayer.test
|
||||
messages:
|
||||
- message_type: incoming
|
||||
content: "Hello, I'm having trouble with the mobile app."
|
||||
- message_type: outgoing
|
||||
sender: danny@paperlayer.test
|
||||
content: "Sorry to hear that! Can you tell me what specific issue you're experiencing?"
|
||||
- message_type: incoming
|
||||
content: "The app keeps crashing when I try to upload a document."
|
||||
- message_type: outgoing
|
||||
sender: danny@paperlayer.test
|
||||
content: "I understand how frustrating that must be. Let me help you troubleshoot this issue right away."
|
||||
- name: "David Chen"
|
||||
email: "dchen@sample.test"
|
||||
gender: 'male'
|
||||
conversations:
|
||||
- channel: Channel::Email
|
||||
source_id: "dchen@sample.test"
|
||||
assignee: ben@paperlayer.test
|
||||
messages:
|
||||
- message_type: incoming
|
||||
content: "I need assistance with integrating your API."
|
||||
- message_type: outgoing
|
||||
sender: ben@paperlayer.test
|
||||
content: "I'll be happy to help with the API integration. What programming language are you using?"
|
||||
- message_type: incoming
|
||||
content: "We're using Python for our backend."
|
||||
- message_type: outgoing
|
||||
sender: ben@paperlayer.test
|
||||
content: "Great! I'll send you our Python SDK documentation and some sample code to get you started."
|
||||
|
||||
Reference in New Issue
Block a user