Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ GEM
notiffany (0.1.1)
nenv (~> 0.1)
shellany (~> 0.0)
onebox (1.8.36)
onebox (1.8.40)
fast_blank (>= 1.0.0)
htmlentities (~> 4.3)
moneta (~> 1.0)
Expand Down
2 changes: 1 addition & 1 deletion README.rdoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
= Notebook.ai
= Notebook.ai
{<img src="https://travis-ci.org/indentlabs/notebook.png?branch=master" alt="Build Status" />}[https://travis-ci.org/indentlabs/notebook]
{<img src="https://codeclimate.com/github/indentlabs/notebook/badges/gpa.svg" />}[https://codeclimate.com/github/indentlabs/notebook]
{<img src="https://codeclimate.com/github/indentlabs/notebook/badges/coverage.svg" />}[https://codeclimate.com/github/indentlabs/notebook/coverage]
Expand Down
5 changes: 5 additions & 0 deletions app/controllers/main_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ def comingsoon
def dashboard
return redirect_to new_user_session_path unless user_signed_in?

# if user_signed_in? && current_user.universes.count > 1 && @universe_scope.nil?
# redirect_to universes_path
# return
# end

@content_types = (
Rails.application.config.content_types[:all].map(&:name) & # Use config to dictate order
current_user.user_content_type_activators.pluck(:content_type)
Expand Down
278 changes: 41 additions & 237 deletions app/controllers/subscriptions_controller.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
class SubscriptionsController < ApplicationController
before_action :authenticate_user!
protect_from_forgery except: :stripe_webhook

# General billing page
def new
return redirect_to new_user_session_path, notice: t(:no_do_permission) unless user_signed_in?

Mixpanel::Tracker.new(Rails.application.config.mixpanel_token).track(current_user.id, 'viewed billing page', {
'current billing plan': current_user.selected_billing_plan_id,
'content count': current_user.content_count
Expand All @@ -22,132 +22,20 @@ def show

def change
new_plan_id = params[:stripe_plan_id]
possible_plan_ids = BillingPlan.where(available: true).map(&:stripe_plan_id)

raise "Invalid billing plan ID: #{new_plan_id}" unless possible_plan_ids.include? new_plan_id

# If the user is changing to Starter, go ahead and cancel any active subscriptions and do it
if new_plan_id == 'starter'
current_user.active_subscriptions.each do |subscription|
subscription.update(end_date: Time.now)
end

if current_user.selected_billing_plan_id.nil?
old_billing_plan = BillingPlan.new(name: 'No billing plan', monthly_cents: 0)
else
old_billing_plan = BillingPlan.find(current_user.selected_billing_plan_id)
end
new_billing_plan = BillingPlan.find_by(stripe_plan_id: new_plan_id, available: true)
current_user.selected_billing_plan_id = new_billing_plan.id

# Remove any bonus bandwidth our old plan granted
current_user.upload_bandwidth_kb -= old_billing_plan.bonus_bandwidth_kb

current_user.save
possible_plan_ids = SubscriptionService.available_plans.pluck(:stripe_plan_id)

Subscription.create(
user: current_user,
billing_plan: new_billing_plan,
start_date: Time.now,
end_date: Time.now.end_of_day + 5.years
)

unless Rails.env.test?
stripe_customer = Stripe::Customer.retrieve current_user.stripe_customer_id
stripe_subscription = stripe_customer.subscriptions.data[0]
stripe_subscription.save
end

report_subscription_change_to_slack current_user, old_billing_plan, new_billing_plan

flash[:notice] = "You have been successfully downgraded to Starter." #todo proration/credit
return redirect_to subscription_path
unless possible_plan_ids.include?(new_plan_id)
raise "Invalid billing plan ID: #{new_plan_id}"
end

# Fetch current subscription
stripe_customer = Stripe::Customer.retrieve current_user.stripe_customer_id
stripe_subscription = stripe_customer.subscriptions.data[0]

# If the user already has a payment method on file, change their plan and add a new subscription
if stripe_customer.sources.total_count > 0
# Cancel any active subscriptions, since we're changing plans
current_user.active_subscriptions.each do |subscription|
subscription.update(end_date: Time.now)
end

# Change subscription plan if they already have a payment method on file
stripe_subscription.plan = new_plan_id
begin
stripe_subscription.save unless Rails.env.test?
rescue Stripe::CardError => e
flash[:alert] = "We couldn't upgrade you to Premium because #{e.message.downcase} Please double check that your information is correct."
return redirect_to :back
end

# If this is the first time this user is subscribing to Premium, gift them (and their referrer, if applicable) feature votes and space
existing_premium_subscriptions = current_user.subscriptions.where(billing_plan_id: BillingPlan::PREMIUM_IDS)
unless existing_premium_subscriptions.any?
referring_user = current_user.referrer || current_user

# First-time premium!
# +100 MB
current_user.update upload_bandwidth_kb: current_user.upload_bandwidth_kb + 100_000
current_user.reload

# +1 vote
current_user.votes.create
# +1 vote if referred
current_user.votes.create if referring_user.present?

# +1 raffle entry
current_user.raffle_entries.create
# +1 raffle entry if referred
current_user.raffle_entries.create if referring_user.present?

if referring_user
# +100MB
referring_user.update upload_bandwidth_kb: referring_user.upload_bandwidth_kb + 100_000

# +2 votes
referring_user.votes.create
referring_user.votes.create

# +2 raffle entries
referring_user.raffle_entries.create
referring_user.raffle_entries.create
end
end

if current_user.selected_billing_plan_id.nil?
old_billing_plan = BillingPlan.new(name: 'No billing plan', monthly_cents: 0)
else
old_billing_plan = BillingPlan.find(current_user.selected_billing_plan_id)
end
new_billing_plan = BillingPlan.find_by(stripe_plan_id: new_plan_id, available: true)
current_user.selected_billing_plan_id = new_billing_plan.id

# Add any bonus bandwidth our new plan grants, unless we're moving from Premium to Premium
premium_ids = [3, 4, 5, 6]
if !premium_ids.include?(current_user.selected_billing_plan_id) && premium_ids.include?(new_plan_id)
current_user.upload_bandwidth_kb += new_billing_plan.bonus_bandwidth_kb
end

current_user.save
result = move_user_to_plan_requested(new_plan_id)

Subscription.create(
user: current_user,
billing_plan: new_billing_plan,
start_date: Time.now,
end_date: Time.now.end_of_day + 5.years
)

report_subscription_change_to_slack current_user, old_billing_plan, new_billing_plan

flash[:notice] = "You have been successfully upgraded to #{new_billing_plan.name}!"
redirect_to subscription_path
else
# If they don't have a payment method on file, redirect them to collect one
if result == :payment_method_needed
redirect_to payment_info_path(plan: new_plan_id)
elsif result == :failed_card
return
else
redirect_to(subscription_path, notice: "Your plan was successfully changed.")
end
end

Expand All @@ -162,6 +50,7 @@ def change
# stripe_subscription.delete(at_period_end: true)
# end

# Billing information page
def information
@selected_plan = BillingPlan.find_by(stripe_plan_id: params['plan'], available: true)
@stripe_customer = Stripe::Customer.retrieve(current_user.stripe_customer_id)
Expand All @@ -172,11 +61,8 @@ def information
}) if Rails.env.production?
end

# Save a payment method
def information_change
# No idea why current_user is nil for this endpoint (maybe CSRF isn't passing through correctly?) but
# calling authenticate_user! here reauths the user and sets current_user
authenticate_user!

valid_token = params[:stripeToken]
raise "Invalid token" if valid_token.nil?

Expand All @@ -195,90 +81,17 @@ def information_change
return redirect_to :back
end

notice = []

# After saving the user's payment method, move them over to the associated billing plan
new_billing_plan = BillingPlan.find_by(stripe_plan_id: params[:plan], available: true)
if new_billing_plan
if current_user.selected_billing_plan_id.nil?
old_billing_plan = BillingPlan.new(name: 'No billing plan', monthly_cents: 0)
else
old_billing_plan = BillingPlan.find(current_user.selected_billing_plan_id)
end
current_user.selected_billing_plan_id = new_billing_plan.id

# Remove any bonus bandwidth our old plan granted
current_user.upload_bandwidth_kb -= old_billing_plan.bonus_bandwidth_kb

# Add any bonus bandwidth our new plan grants
current_user.upload_bandwidth_kb += new_billing_plan.bonus_bandwidth_kb

current_user.save

stripe_subscription.plan = new_billing_plan.stripe_plan_id
begin
stripe_subscription.save
rescue Stripe::CardError => e
flash[:alert] = "We couldn't upgrade you to Premium because #{e.message.downcase} Please double check that your information is correct."
return redirect_to :back
end

# End all currently-active subscriptions
current_user.active_subscriptions.each do |subscription|
subscription.update(end_date: Time.now)
end

# If this is the first time this user is subscribing to Premium, gift them (and their referrer, if applicable) feature votes and space
existing_premium_subscriptions = current_user.subscriptions.where(billing_plan_id: BillingPlan::PREMIUM_IDS)
unless existing_premium_subscriptions.any?
referring_user = current_user.referrer || current_user

# First-time premium!
# +100 MB
current_user.update upload_bandwidth_kb: current_user.upload_bandwidth_kb + 100_000
current_user.reload
new_plan_id = params[:plan]
result = move_user_to_plan_requested(new_plan_id)

# +1 vote
current_user.votes.create
# +1 vote if referred
current_user.votes.create if referring_user.present?

# +1 raffle entry
current_user.raffle_entries.create
# +1 raffle entry if referred
current_user.raffle_entries.create if referring_user.present?

if referring_user
# +100MB
referring_user.update upload_bandwidth_kb: referring_user.upload_bandwidth_kb + 100_000

# +2 votes
referring_user.votes.create
referring_user.votes.create

# +2 raffle entries
referring_user.raffle_entries.create
referring_user.raffle_entries.create
end
end

# And create a subscription for them for the current plan
Subscription.create(
user: current_user,
billing_plan: new_billing_plan,
start_date: Time.now,
end_date: Time.now.end_of_day + 31.days
)

report_subscription_change_to_slack current_user, old_billing_plan, new_billing_plan

notice << "you have been successfully upgraded to #{new_billing_plan.name}"
if result == :payment_method_needed
redirect_to payment_info_path(plan: new_plan_id)
elsif result == :failed_card
return
else
redirect_to(subscription_path, notice: 'Your plan was successfully changed.')
end

notice << "Your payment method has been successfully saved"

flash[:notice] = "#{notice.reverse.to_sentence}."
redirect_to subscription_path
end

def delete_payment_method
Expand Down Expand Up @@ -310,40 +123,31 @@ def stripe_webhook
#todo handle webhooks
end

def report_subscription_change_to_slack user, from, to
return unless Rails.env == 'production'
slack_hook = ENV['SLACK_HOOK']
return unless slack_hook

notifier = Slack::Notifier.new slack_hook,
channel: '#subscriptions',
username: 'tristan'
private

if from.nil? || to.nil?
delta = ":tada: LOL :tada:"
elsif from.monthly_cents < to.monthly_cents
delta = ":tada: *UPGRADE* :tada:"
elsif from.monthly_cents == to.monthly_cents
delta = ":tada: ... sidegrade ... :tada:"
def move_user_to_plan_requested(plan_id)
if plan_id == 'starter'
process_plan_change(current_user, plan_id)
else
delta = ":wave: Downgrade"
end
stripe_customer = Stripe::Customer.retrieve current_user.stripe_customer_id

total_subscriptions = 0
monthly_rev_cents = 0
billing_plans_with_prices = BillingPlan.where.not(monthly_cents: 0).pluck(:id, :monthly_cents)
billing_plans_with_prices.each do |plan_id, monthly_cents|
users_on_this_plan = User.where(selected_billing_plan_id: plan_id).count
total_subscriptions += users_on_this_plan
monthly_rev_cents += monthly_cents * users_on_this_plan
# If we're upgrading to premium, we want to check that a payment method
# is already on file. If it is, we process the plan change. If it's not,
# we redirect to the payment method page.
if stripe_customer.sources.total_count > 0
process_plan_change(current_user, plan_id)
else
return :payment_method_needed
end
end
end

notifier.ping [
"#{delta} for #{user.email.split('@').first}@ (##{user.id})",
"From: *#{from.name}* ($#{from.monthly_cents / 100.0}/month)",
"To: *#{to.name}* (#{to.stripe_plan_id}) ($#{to.monthly_cents / 100.0}/month)",
"#{total_subscriptions} subscriptions total $#{'%.2f' % (monthly_rev_cents / 100)}/mo"
].join("\n")
def process_plan_change(user, new_plan_id)
# General flow we're going to take here:
# 1. Cancel all existing plans, reversing their benefits
SubscriptionService.cancel_all_existing_subscriptions(user)

# 2. Add a new plan, adding its benefits
SubscriptionService.add_subscription(user, new_plan_id)
end
end
2 changes: 1 addition & 1 deletion app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def delete_my_account # :(
stripe_subscription.plan = 'starter'
stripe_subscription.save

report_user_deletion_to_slack current_user
report_user_deletion_to_slack(current_user)

current_user.really_destroy!
redirect_to root_path, notice: 'Your account has been deleted. We will miss you greatly!'
Expand Down
1 change: 0 additions & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ def referrer
has_many :user_content_type_activators, dependent: :destroy

def contributable_universes

@user_contributable_universes ||= begin
# todo email confirmation needs to happy for data safety / privacy (only verified emails)
contributor_by_email = Contributor.where(email: self.email).pluck(:universe_id)
Expand Down
Loading