From 6a07efb461449a3a314c52c9118bd87e82d66e76 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 2 Jun 2025 12:43:07 +0530 Subject: [PATCH] feat: add csat to account seeder --- lib/seeders/account_seeder.rb | 14 ++++++ lib/seeders/csat_seeder.rb | 88 +++++++++++++++++++++++++++++++++++ lib/seeders/inbox_seeder.rb | 33 +++++++++++-- lib/seeders/seed_data.yml | 53 ++++++++++++++++++++- 4 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 lib/seeders/csat_seeder.rb diff --git a/lib/seeders/account_seeder.rb b/lib/seeders/account_seeder.rb index ba46638c5..e7fa2d126 100644 --- a/lib/seeders/account_seeder.rb +++ b/lib/seeders/account_seeder.rb @@ -25,6 +25,7 @@ class Seeders::AccountSeeder seed_canned_responses seed_inboxes seed_contacts + seed_csat_responses end def set_up_account @@ -126,11 +127,20 @@ class Seeders::AccountSeeder def create_conversation(contact_inbox:, conversation_data:) assignee = User.from_email(conversation_data['assignee']) if conversation_data['assignee'].present? + + # Assign random agent if no assignee specified and inbox has CSAT enabled + assignee = @account.agents.sample if assignee.nil? && contact_inbox.inbox.csat_survey_enabled + 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? + + # Resolve some conversations (about 60%) that have assignees to generate CSAT data + return unless assignee.present? && rand > 0.4 + + conversation.update!(status: :resolved) end def create_messages(conversation:, messages:) @@ -155,4 +165,8 @@ class Seeders::AccountSeeder 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 diff --git a/lib/seeders/csat_seeder.rb b/lib/seeders/csat_seeder.rb new file mode 100644 index 000000000..41f9eca00 --- /dev/null +++ b/lib/seeders/csat_seeder.rb @@ -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 \ No newline at end of file diff --git a/lib/seeders/inbox_seeder.rb b/lib/seeders/inbox_seeder.rb index 9ee750a63..0f8f95d7b 100644 --- a/lib/seeders/inbox_seeder.rb +++ b/lib/seeders/inbox_seeder.rb @@ -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 diff --git a/lib/seeders/seed_data.yml b/lib/seeders/seed_data.yml index 08cb5549b..eed4f94ab 100644 --- a/lib/seeders/seed_data.yml +++ b/lib/seeders/seed_data.yml @@ -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."