diff --git a/admin/app/admin/jam_ruby_users.rb b/admin/app/admin/jam_ruby_users.rb index 0be6f19c3..2a99b3eb8 100644 --- a/admin/app/admin/jam_ruby_users.rb +++ b/admin/app/admin/jam_ruby_users.rb @@ -71,7 +71,7 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do end member_action :end_trial, :method => :get do - if DateTime.now - 2.days < resource.subscription_trial_ends_at + if Time.now - 2.days < resource.subscription_trial_ends_at resource.subscription_trial_ends_at = 3.days.ago resource.save! redirect_to :back, {notice: "User's trial ended"} @@ -156,9 +156,10 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do row "Subscription" do |user| div do attributes_table do - row :desired_plan_code, 'hi' row :subscription_plan_code + row :desired_plan_code row :admin_override_plan_code + row :admin_override_ends_at row :recurly_subscription_state row :recurly_subscription_id row :desired_plan_code_set_at @@ -175,7 +176,7 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do 'DESIRED PLAN CODE = What plan the user has selected in the UI' end div do - 'SUBSCIRPTION PLAN CODE = What plan the user actually has' + 'SUBSCRIPTION PLAN CODE = What plan the user actually has' end div do div do @@ -190,28 +191,19 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do 'Give Free Plan Actions' end h4 do - 'sets secret override to give user a free plan' + 'sets secret override to give user a free plan (link goes to another page)' end div do + link_to("Give No-Payment Plan", edit_admin_subscription_path(user.id)) + end - link_to("give free silver plan", give_free_plan_admin_user_path(user.id, plan_code: 'jamsubsilver'), :data => {:confirm => 'Are you sure?'}) - end - div do - link_to("give free gold plan", give_free_plan_admin_user_path(user.id, plan_code: 'jamsubgold'), :data => {:confirm => 'Are you sure?'}) - end - div do - link_to("give free platinum plan", give_free_plan_admin_user_path(user.id, plan_code: 'jamsubplatinum'), :data => {:confirm => 'Are you sure?'}) - end - div do - link_to("revoke free plan", revoke_free_plan_admin_user_path(user.id), :data => {:confirm => 'Are you sure?'}) - end end div do h3 do 'Change Plan Actions' end h4 do - 'exactly as if the user did it in the UI' + 'Change desired plan xactly as if the user did it on /client#/accounts/subscription' end div do link_to("change plan to silver", change_to_plan_admin_user_path(user.id, 'jamsubsilver'), :data => {:confirm => 'Are you sure?'}) diff --git a/admin/app/admin/subscription_override.rb b/admin/app/admin/subscription_override.rb new file mode 100644 index 000000000..78bbb5c36 --- /dev/null +++ b/admin/app/admin/subscription_override.rb @@ -0,0 +1,26 @@ +ActiveAdmin.register User, :as => 'Subscription' do + + menu :label => 'Subscription', :parent => 'Users' + + form title: 'Use This To Give a No-Payment Subscription' do |f| + inputs 'Details' do + input :admin_override_touch, :as => :hidden, value: 'true' + input :admin_override_reason, :as => :text + input :admin_override_plan_code, :as => :select, :collection => SubscriptionDefinitions::MONTHLY_PLANS + ['Remove Override'] + input :admin_override_ends_at, as: :datepicker, + datepicker_options: { + min_date: Date.today, + max_date: "+10Y" + } + li "User has admin override set to #{f.object.admin_override_plan_code}. Lasts until #{f.object.admin_override_ends_at}" if !f.object.admin_override_plan_code.nil? + li "User does not have admin override. They are currently on the #{f.object.subscription_plan_code ? f.object.subscription_plan_code : 'Free'} plan" if f.object.admin_override_plan_code.nil? + end + panel 'Instructions' do + "If you select a plan, the user will have their current subscription (if any) cancelled and set to the new plan for free. If you instead select Remove Override, you can cancel the gifted plan and the user will be o normal free-tier user again." + end + para "Press cancel to return to the list without saving." + actions + end + +end + diff --git a/admin/config/initializers/jam_ruby_user.rb b/admin/config/initializers/jam_ruby_user.rb index b6e0ca6e5..bb603166e 100644 --- a/admin/config/initializers/jam_ruby_user.rb +++ b/admin/config/initializers/jam_ruby_user.rb @@ -1,7 +1,8 @@ class JamRuby::User - attr_accessible :admin, :raw_password, :musician, :can_invite, :photo_url, :session_settings, :confirm_url, :teacher_attributes, :email_template, :is_platform_instructor # :invite_email + attr_accessible :admin, :raw_password, :musician, :can_invite, :photo_url, :session_settings, :confirm_url, :teacher_attributes, :email_template, :is_platform_instructor, :admin_override_plan_code, :admin_override_ends_at, :admin_override_touch, :admin_override_reason, as: :admin # :invite_email + attr_accessor :admin_override_touch accepts_nested_attributes_for :teacher, allow_destroy: true ransacker :jamuser_full_name, formatter: proc { |v| v.mb_chars.downcase.to_s } do |parent| @@ -10,6 +11,27 @@ [Arel::Nodes::SqlLiteral.new("' '"), User.arel_table[:first_name], User.arel_table[:last_name]])]) end + + after_save :admin_override_handler_sync + + before_validation do + if self.admin_override_plan_code == 'Remove Override' + puts "Remove override just means set it to free again. so set to nil" + self.admin_override_plan_code = nil + end + end + + def admin_override_handler_sync + if admin_override_touch + self.admin_override_touch = false + @client = RecurlyClient.new + # first, when ever we admin code it, set them to free. This would cancel any existing plan. We don't want them geting charged in any scenario where we are doing this acitvity + puts "Setting desired plan to free. Potentially cancelling existing." + result, subscription, account = @client.update_desired_subscription(self, nil) + + self.update_admin_override_plan_code(self.admin_override_plan_code) + end + end def raw_password '' end diff --git a/db/up/find_sessions_2020.sql b/db/up/find_sessions_2020.sql index be85e8d2b..8d136bf5c 100644 --- a/db/up/find_sessions_2020.sql +++ b/db/up/find_sessions_2020.sql @@ -99,6 +99,8 @@ ALTER TABLE users ADD COLUMN recurly_subscription_state VARCHAR(20) DEFAULT NULL ALTER TABLE users ADD COLUMN subscription_plan_code VARCHAR(100) DEFAULT NULL; ALTER TABLE users ADD COLUMN desired_plan_code VARCHAR(100) DEFAULT NULL; ALTER TABLE users ADD COLUMN admin_override_plan_code VARCHAR(100) DEFAULT NULL; +ALTER TABLE users ADD COLUMN admin_override_ends_at DATE; +ALTER TABLE users ADD COLUMN admin_override_reason VARCHAR; ALTER TABLE users ADD COLUMN desired_plan_code_set_at TIMESTAMP; ALTER TABLE users ADD COLUMN subscription_plan_code_set_at TIMESTAMP; ALTER TABLE users ADD COLUMN subscription_last_checked_at TIMESTAMP; @@ -111,8 +113,7 @@ ALTER TABLE users ADD COLUMN subscription_trial_ends_at TIMESTAMP NOT NULL DEFAU ALTER TABLE users ADD COLUMN subscription_plan_reason varchar(20); --UPDATE users set subscription_trial_ends_at = (CURRENT_TIMESTAMP + '30 days'::interval), subscription_plan_code = 'jamsubgold'; -UPDATE users set subscription_trial_ends_at = '2021-01-01', subscription_plan_code = 'jamsubgold'; -UPDATE users set subscription_plan_code = 'jamsubplatinum'; +UPDATE users set subscription_trial_ends_at = '2021-01-01', subscription_plan_code = 'jamsubplatinum'; UPDATE users set stored_credit_card = true where recurly_code is not null; diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index d6324131c..9088063dc 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -398,7 +398,7 @@ module JamRuby any = false User .where('subscription_last_checked_at is NULL OR users.subscription_last_checked_at < ?', 1.days.ago) - .where("recurly_subscription_id IS NOT NULL OR subscription_sync_code IS NULL or (subscription_sync_code not in ('trial_ended', 'no_recurly_account', 'admin_control', 'school_license', 'no_subscription_or_expired'))") + .where("recurly_subscription_id IS NOT NULL OR subscription_sync_code IS NULL or (subscription_sync_code not in ('trial_ended', 'no_recurly_account', 'school_license', 'no_subscription_or_expired'))") .order('subscription_last_checked_at ASC NULLS FIRST, recurly_code ASC NULLS LAST') .limit(1000) .each do |user| @@ -411,7 +411,7 @@ module JamRuby # for testing when no results #any = true - sleep(20) + #sleep(20) # eat up work to do for up to 30 minutes break if !any || Time.now - 30.minutes > start @@ -2881,12 +2881,15 @@ module JamRuby self.admin_override_plan_code = plan_code self.subscription_plan_code = plan_code self.subscription_plan_code_set_at = DateTime.now + if plan_code.nil? + self.admin_override_ends_at = nil + end self.save(validate: false) end def subscription_trial_ended? - subscription_trial_ends_at.nil? || DateTime.now > subscription_trial_ends_at + subscription_trial_ends_at.nil? || Time.now > subscription_trial_ends_at end def recurly_link_to_account diff --git a/ruby/lib/jam_ruby/recurly_client.rb b/ruby/lib/jam_ruby/recurly_client.rb index de88cf060..ec722c923 100644 --- a/ruby/lib/jam_ruby/recurly_client.rb +++ b/ruby/lib/jam_ruby/recurly_client.rb @@ -463,14 +463,29 @@ module JamRuby begin # edge case: admin controlled if user.admin_override_plan_code - puts "admin controlled plan #{user.email}" - user.subscription_plan_code = user.admin_override_plan_code - user.subscription_plan_code_set_at = DateTime.now - user.subscription_last_checked_at = DateTime.now - user.subscription_sync_code = 'admin_control' - user.subscription_sync_msg = "admin override - plan_code set to #{user.admin_override_plan_code}" - user.save(validate: false) - return + # check if it's expired first... + if Time.now > user.admin_override_ends_at.to_time + puts "admin control expired. clear override and set Free plan" + user.admin_override_plan_code = nil + # logic below will catch this + #user.subscription_plan_code = nil + user.admin_override_ends_at = nil + user.subscription_sync_code = 'undo_admin_control' + user.subscription_sync_msg = "admin control expired. clear override and set Free plan" + user.subscription_last_checked_at = Time.now + user.save(validate: false) + # don't return; let this fall through to next states + else + puts "admin controlled plan #{user.email}" + user.subscription_plan_code = user.admin_override_plan_code + user.subscription_plan_code_set_at = Time.now + user.subscription_last_checked_at = Time.now + user.subscription_sync_code = 'admin_control' + user.subscription_sync_msg = "admin override - plan_code set to #{user.admin_override_plan_code}" + user.save(validate: false) + return + end + end # edge case: user is in a licensed school @@ -497,7 +512,7 @@ module JamRuby end # if the trial has ended, but it was within 2 days of ending the trial date, give the user some leeway - if user.subscription_trial_ended? && (user.subscription_trial_ends_at.nil? || (DateTime.now < ( user.subscription_trial_ends_at + 2.days ))) + if user.subscription_trial_ended? && (!user.subscription_trial_ends_at.nil? && (Time.now < ( user.subscription_trial_ends_at + 2.days ))) puts "user recently ended trial; ignore them #{user.email}" user.subscription_last_checked_at = DateTime.now user.subscription_sync_code = 'trial_recently_ended' @@ -522,11 +537,12 @@ module JamRuby account = get_account(user) if account.nil? - puts "Account is nil? #{user.email}. Strange" + puts "Account is nil? #{user.email}. Strange. Could happen in some weird admin messing around scenarios" user.subscription_last_checked_at = DateTime.now user.save(validate: false) user.subscription_sync_code = 'no_recurly_account' user.subscription_sync_msg = "user has no recurly account - plan_code not altered" + user.save(validate: false) return end diff --git a/ruby/lib/jam_ruby/subscription_definitions.rb b/ruby/lib/jam_ruby/subscription_definitions.rb index a409df052..c5d5e46e3 100644 --- a/ruby/lib/jam_ruby/subscription_definitions.rb +++ b/ruby/lib/jam_ruby/subscription_definitions.rb @@ -17,6 +17,12 @@ module JamRuby PLATINUM_PLAY_TIME_PER_SESSION = nil # unlimited PLATINUM_PLAY_TIME_PER_MONTH = nil # unlimited + MONTHLY_PLANS = [ + nil, + JAM_SILVER, + JAM_GOLD, + JAM_PLATINUM + ] FREE_PLAN = { play_time_per_month: FREE_PLAY_TIME_PER_MONTH, diff --git a/ruby/spec/jam_ruby/models/user_subscriptions_spec.rb b/ruby/spec/jam_ruby/models/user_subscriptions_spec.rb index 9efdce26c..85449f8ba 100644 --- a/ruby/spec/jam_ruby/models/user_subscriptions_spec.rb +++ b/ruby/spec/jam_ruby/models/user_subscriptions_spec.rb @@ -16,8 +16,8 @@ describe "User Subscriptions" do user1.reload - user1.subscription_sync_code.should be_nil - user1.subscription_last_checked_at.should be_nil + user1.subscription_sync_code.should == 'trial_recently_ended' + user1.subscription_last_checked_at.should_not be_nil end it "user not in trial" do @@ -43,4 +43,34 @@ describe "User Subscriptions" do user1.subscription_plan_code.should be_nil end + it "revert admin user down" do + user1.subscription_plan_code = SubscriptionDefinitions::JAM_PLATINUM + user1.subscription_trial_ends_at = 1.days.ago + user1.admin_override_plan_code = SubscriptionDefinitions::JAM_PLATINUM + user1.admin_override_ends_at = 10.days.from_now + user1.save! + + User.subscription_sync + + user1.reload + + user1.subscription_sync_code.should == "admin_control" + user1.subscription_last_checked_at.should_not be_nil + user1.subscription_plan_code.should == SubscriptionDefinitions::JAM_PLATINUM + + user1.subscription_trial_ends_at = 3.days.ago + user1.admin_override_ends_at = 10.days.ago + user1.subscription_last_checked_at = 2.days.ago + user1.save! + + User.subscription_sync + user1.reload + + user1.subscription_sync_code.should == "trial_ended" + user1.subscription_last_checked_at.should_not be_nil + user1.subscription_plan_code.should be_nil + + + end + end diff --git a/web/app/assets/javascripts/utils.js b/web/app/assets/javascripts/utils.js index cae4ba761..4593f283a 100644 --- a/web/app/assets/javascripts/utils.js +++ b/web/app/assets/javascripts/utils.js @@ -877,7 +877,7 @@ } context.JK.alertSupportedNeeded = function(additionalContext) { - var $item = context.JK.Banner.showAlert(additionalContext + '

Please contact support.'); + var $item = context.JK.Banner.showAlert(additionalContext + '

Please contact support.'); context.JK.popExternalLinks($item); return $item; } diff --git a/web/app/views/corps/contact.html.erb b/web/app/views/corps/contact.html.erb index f1eedfeec..fe2c5e0ba 100644 --- a/web/app/views/corps/contact.html.erb +++ b/web/app/views/corps/contact.html.erb @@ -4,7 +4,7 @@

Thank you for your interest in JamKazam. Depending on your specific interest, please use one of the following avenues to reach out to us. We look forward to hearing from you!

Support

-

For technical support and help using our products and services, please visit the JamKazam Support Center.

+

For technical support and help using our products and services, please visit the JamKazam Support Center.

Partnerships

For partnering inquiries, please contact us at: partners@jamkazam.com.

Media

diff --git a/web/app/views/dialogs/_rsvpCancelDialog.html.haml b/web/app/views/dialogs/_rsvpCancelDialog.html.haml index 8912c7041..190adf371 100644 --- a/web/app/views/dialogs/_rsvpCancelDialog.html.haml +++ b/web/app/views/dialogs/_rsvpCancelDialog.html.haml @@ -23,7 +23,7 @@ %textarea.txtComment{id: 'txtComment', rows: '2', placeholder: 'Enter a comment...'} .buttons .left - %a.button-orange{:href => 'http://jamkazam.desk.com', :rel => 'external', :target => '_blank'} HELP + %a.button-orange{:href => 'https://jamkazam.freshdesk.com', :rel => 'external', :target => '_blank'} HELP .right %a.button-grey{:id => 'btnCancel', 'layout-action' => 'close'} CANCEL %a.button-orange{:id => 'btnCancelRsvp'} CANCEL RSVP \ No newline at end of file diff --git a/web/app/views/dialogs/_rsvpSubmitDialog.html.haml b/web/app/views/dialogs/_rsvpSubmitDialog.html.haml index f7eb20bbf..5dbae7558 100644 --- a/web/app/views/dialogs/_rsvpSubmitDialog.html.haml +++ b/web/app/views/dialogs/_rsvpSubmitDialog.html.haml @@ -27,7 +27,7 @@ .buttons .left - %a#btnHelp.button-grey{:href => 'http://jamkazam.desk.com', :rel => 'external', :target => '_blank'} HELP + %a#btnHelp.button-grey{:href => 'https://jamkazam.freshdesk.com', :rel => 'external', :target => '_blank'} HELP .right %a#btnCancel.button-grey{'layout-action' => 'close'} CANCEL %a#btnSubmitRsvp.button-orange SUBMIT RSVP \ No newline at end of file diff --git a/web/app/views/dialogs/_sessionCancelDialog.html.haml b/web/app/views/dialogs/_sessionCancelDialog.html.haml index 8c2ca4664..f4e9512f0 100644 --- a/web/app/views/dialogs/_sessionCancelDialog.html.haml +++ b/web/app/views/dialogs/_sessionCancelDialog.html.haml @@ -16,7 +16,7 @@ %br/ %br/ .left - %a.button-orange{:href => 'http://jamkazam.desk.com/', :rel => 'external', :target => '_blank'} HELP + %a.button-orange{:href => 'https://jamkazam.freshdesk.com', :rel => 'external', :target => '_blank'} HELP .right %a.button-grey{:id => 'btnCancel', 'layout-action' => 'close'} CANCEL %a.button-orange{:id => 'btnCancelSession'} CANCEL SESSION