diff --git a/ruby/db/migrate/20250227125441_add_profile_complete_columns_to_users.rb b/ruby/db/migrate/20250227125441_add_profile_complete_columns_to_users.rb
index 2fef976d3..f80af7069 100644
--- a/ruby/db/migrate/20250227125441_add_profile_complete_columns_to_users.rb
+++ b/ruby/db/migrate/20250227125441_add_profile_complete_columns_to_users.rb
@@ -7,9 +7,9 @@
execute "ALTER TABLE users ADD COLUMN profile_complete_reminder2_sent_at TIMESTAMP"
execute "ALTER TABLE users ADD COLUMN profile_complete_reminder3_sent_at TIMESTAMP"
- User.find_each(batch_size:100) do |user|
- User.where(id:user.id).update_all(profile_completed_at: Time.now)
- end
+ # User.find_each(batch_size:100) do |user|
+ # User.where(id:user.id).update_all(profile_completed_at: Time.now)
+ # end
#User.where('users.id IN (SELECT player_id FROM musicians_instruments) OR users.id IN (SELECT player_id FROM genre_players)').update_all(profile_completed_at: Time.now)
end
def self.down
diff --git a/ruby/db/migrate/20250605092511_add_signup_survey_sent_at_to_users.rb b/ruby/db/migrate/20250605092511_add_signup_survey_sent_at_to_users.rb
index f8f271c99..fdd98c0cc 100644
--- a/ruby/db/migrate/20250605092511_add_signup_survey_sent_at_to_users.rb
+++ b/ruby/db/migrate/20250605092511_add_signup_survey_sent_at_to_users.rb
@@ -1,9 +1,9 @@
class AddSignupSurveySentAtToUsers < ActiveRecord::Migration
def self.up
execute "ALTER TABLE users ADD COLUMN signup_survey_sent_at TIMESTAMP"
- User.find_each(batch_size:100) do |user|
- User.where(id:user.id).update_all(signup_survey_sent_at: Time.now)
- end
+ # User.find_each(batch_size:100) do |user|
+ # User.where(id:user.id).update_all(signup_survey_sent_at: Time.now)
+ # end
end
def self.down
execute "ALTER TABLE users DROP COLUMN signup_survey_sent_at"
diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb
index fb13366a1..ac8de9372 100755
--- a/ruby/lib/jam_ruby.rb
+++ b/ruby/lib/jam_ruby.rb
@@ -125,6 +125,7 @@ require "jam_ruby/lib/email_signup_survey"
require "jam_ruby/lib/gear_setup_reminder"
require "jam_ruby/lib/test_gear_reminder"
require "jam_ruby/lib/group_session_reminder"
+require "jam_ruby/lib/trial_expires_reminder"
require "jam_ruby/amqp/amqp_connection_manager"
require "jam_ruby/database"
require "jam_ruby/message_factory"
diff --git a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb
index 81b42ac7e..42678bda3 100644
--- a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb
+++ b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb
@@ -528,6 +528,30 @@ module JamRuby
end
end
+ def trial_expires_reminder1(user)
+ @user = user
+ mail(:to => user.email, :subject => I18n.t('user_mailer.trial_expires_reminder1.subject')) do |format|
+ format.text
+ format.html { render layout: "user_mailer_beta" }
+ end
+ end
+
+ def trial_expires_reminder2(user)
+ @user = user
+ mail(:to => user.email, :subject => I18n.t('user_mailer.trial_expires_reminder2.subject')) do |format|
+ format.text
+ format.html { render layout: "user_mailer_beta" }
+ end
+ end
+
+ def trial_expires_reminder3(user)
+ @user = user
+ mail(:to => user.email, :subject => I18n.t('user_mailer.trial_expires_reminder3.subject')) do |format|
+ format.text
+ format.html { render layout: "user_mailer_beta" }
+ end
+ end
+
def signup_survey(user)
@user = user
@subject = I18n.t('user_mailer.signup_survey.subject')
diff --git a/ruby/lib/jam_ruby/resque/scheduled/hourly_job.rb b/ruby/lib/jam_ruby/resque/scheduled/hourly_job.rb
index 1e617f526..87e828396 100644
--- a/ruby/lib/jam_ruby/resque/scheduled/hourly_job.rb
+++ b/ruby/lib/jam_ruby/resque/scheduled/hourly_job.rb
@@ -18,6 +18,7 @@ module JamRuby
GearSetupReminder.send_reminders
TestGearReminder.send_reminders
GroupSessionReminder.send_reminders
+ TrialExpiresReminder.send_reminders
ConnectionManager.new.cleanup_dangling
@@log.info("done")
diff --git a/ruby/spec/mailers/user_mailer_spec.rb b/ruby/spec/mailers/user_mailer_spec.rb
index c4428cea3..1e8c4888c 100644
--- a/ruby/spec/mailers/user_mailer_spec.rb
+++ b/ruby/spec/mailers/user_mailer_spec.rb
@@ -240,11 +240,11 @@ describe UserMailer do
end
it "includes the correct content in the HTML part" do
- expect(mail.html_part.body.to_s).to include("Now that you have set up your gearand checked it out in a solo session on your own")
+ expect(mail.html_part.body.to_s).to include("Now that you have set up your gear and checked it out in a solo session on your own")
end
it "includes the correct content in the text part" do
- expect(mail.text_part.body.to_s).to include("Now that you have set up your gearand checked it out in a solo session on your own")
+ expect(mail.text_part.body.to_s).to include("Now that you have set up your gear and checked it out in a solo session on your own")
end
end
@@ -322,4 +322,115 @@ describe UserMailer do
end
end
+ describe "sends trial expires reminder 1", focus: true do
+ let(:mail) { ActionMailer::Base.deliveries.last }
+
+ before(:each) do
+ ActionMailer::Base.deliveries.clear
+ UserMailer.trial_expires_reminder1(user).deliver_now
+ end
+
+ it "sends exactly one email" do
+ expect(ActionMailer::Base.deliveries.length).to eq(1)
+ end
+
+ it "has the correct from address" do
+ mail['from'].to_s.should == UserMailer::DEFAULT_SENDER
+ end
+
+ it "has the correct recipient" do
+ expect(mail.to).to eq([user.email])
+ end
+
+ it "is multipart" do
+ expect(mail).to be_multipart
+ end
+
+ it "has the expected subject" do
+ expect(mail.subject).to include("Your free gold trial has expired, but you have great options to keep playing!")
+ end
+
+ it "includes the correct content in the HTML part" do
+ expect(mail.html_part.body.to_s).to include("We hope you’ve enjoyed your 30-day free gold trial with JamKazam")
+ end
+
+ it "includes the correct content in the text part" do
+ expect(mail.text_part.body.to_s).to include("We hope you’ve enjoyed your 30-day free gold trial with JamKazam")
+ end
+ end
+
+ describe "sends trial expires reminder 2", focus: true do
+ let(:mail) { ActionMailer::Base.deliveries.last }
+
+ before(:each) do
+ ActionMailer::Base.deliveries.clear
+ UserMailer.trial_expires_reminder2(user).deliver_now
+ end
+
+ it "sends exactly one email" do
+ expect(ActionMailer::Base.deliveries.length).to eq(1)
+ end
+
+ it "has the correct from address" do
+ mail['from'].to_s.should == UserMailer::DEFAULT_SENDER
+ end
+
+ it "has the correct recipient" do
+ expect(mail.to).to eq([user.email])
+ end
+
+ it "is multipart" do
+ expect(mail).to be_multipart
+ end
+
+ it "has the expected subject" do
+ expect(mail.subject).to include("Don’t forget to check your options to keep playing")
+ end
+
+ it "includes the correct content in the HTML part" do
+ expect(mail.html_part.body.to_s).to include("Your 30-day free gold trial with JamKazam has expired")
+ end
+
+ it "includes the correct content in the text part" do
+ expect(mail.text_part.body.to_s).to include("Your 30-day free gold trial with JamKazam has expired")
+ end
+ end
+
+ describe "sends trial expires reminder 3", focus: true do
+ let(:mail) { ActionMailer::Base.deliveries.last }
+
+ before(:each) do
+ ActionMailer::Base.deliveries.clear
+ UserMailer.trial_expires_reminder3(user).deliver_now
+ end
+
+ it "sends exactly one email" do
+ expect(ActionMailer::Base.deliveries.length).to eq(1)
+ end
+
+ it "has the correct from address" do
+ mail['from'].to_s.should == UserMailer::DEFAULT_SENDER
+ end
+
+ it "has the correct recipient" do
+ expect(mail.to).to eq([user.email])
+ end
+
+ it "is multipart" do
+ expect(mail).to be_multipart
+ end
+
+ it "has the expected subject" do
+ expect(mail.subject).to include("One last reminder!")
+ end
+
+ it "includes the correct content in the HTML part" do
+ expect(mail.html_part.body.to_s).to include("Your 30-day free gold trial with JamKazam has expired")
+ end
+
+ it "includes the correct content in the text part" do
+ expect(mail.text_part.body.to_s).to include("Your 30-day free gold trial with JamKazam has expired")
+ end
+ end
+
end
diff --git a/web/config/application.rb b/web/config/application.rb
index ef6447f11..72e55ba7a 100644
--- a/web/config/application.rb
+++ b/web/config/application.rb
@@ -526,6 +526,7 @@ if defined?(Bundler)
config.gear_setup_reminders_effective_from_date = "2025-06-10"
config.test_gear_reminders_effective_from_date = "2025-07-24"
config.group_session_reminders_effective_from_date = "2025-08-12"
+ config.trial_expires_reminders_effective_from_date = "2025-08-17"
config.action_mailer.asset_host = config.action_controller.asset_host
end
diff --git a/web/config/environments/development.rb b/web/config/environments/development.rb
index 4a71c74be..eb08a6617 100644
--- a/web/config/environments/development.rb
+++ b/web/config/environments/development.rb
@@ -131,4 +131,5 @@ SampleApp::Application.configure do
config.gear_setup_reminders_effective_from_date = "2025-06-10"
config.test_gear_reminders_effective_from_date = "2025-07-24"
config.group_session_reminders_effective_from_date = "2025-08-12"
+ config.trial_expires_reminders_effective_from_date = "2025-08-17"
end
diff --git a/web/config/locales/en.yml b/web/config/locales/en.yml
index c369b7a4d..c450dc48f 100644
--- a/web/config/locales/en.yml
+++ b/web/config/locales/en.yml
@@ -247,6 +247,64 @@ en:
And if you get stuck, don’t hesitate to reach out to us to ask for help at support@jamkazam.com.
regards: "Best Regards,"
signature: "JamKazam Team"
+
+ trial_expires_reminder1:
+ subject: "Your free gold trial has expired, but you have great options to keep playing!"
+ greeting: "Hello"
+ paragraph1: |
+ We hope you’ve enjoyed your 30-day free gold trial with JamKazam. If you’ve used it to play music in online sessions with others, below is a summary of your options to keep playing. If you haven’t finished setting up your gear or haven’t played in sessions with others yet, please send us an email at support@jamkazam.com to let us know where you’re stuck. We have a team that would love to help you!
+