mirror of
https://github.com/indentlabs/notebook.git
synced 2025-10-26 11:19:22 +00:00
130 lines
4.7 KiB
Ruby
130 lines
4.7 KiB
Ruby
class SubscriptionService < Service
|
|
#todo: support multiple simultaneous plans
|
|
|
|
def self.add_subscription(user, plan_id)
|
|
related_plan = BillingPlan.find_by(stripe_plan_id: plan_id, available: true)
|
|
raise "Plan #{plan_id} not available for user #{user.id}" if related_plan.nil?
|
|
|
|
# Sync with Stripe (todo pipe into StripeService)
|
|
unless Rails.env.test?
|
|
stripe_customer = Stripe::Customer.retrieve(user.stripe_customer_id)
|
|
stripe_subscription = stripe_customer.subscriptions.data[0]
|
|
|
|
if stripe_subscription.nil?
|
|
# Create a new subscription on Stripe
|
|
Stripe::Subscription.create(customer: user.stripe_customer_id, plan: plan_id)
|
|
stripe_customer = Stripe::Customer.retrieve(user.stripe_customer_id)
|
|
stripe_subscription = stripe_customer.subscriptions.data[0]
|
|
else
|
|
# Edit an existing Stripe subscription
|
|
stripe_subscription.plan = plan_id
|
|
end
|
|
|
|
# Save the change
|
|
begin
|
|
stripe_subscription.save unless Rails.env.test?
|
|
|
|
# Add any bonus bandwidth granted by the plan
|
|
user.update(
|
|
upload_bandwidth_kb: user.upload_bandwidth_kb + related_plan.bonus_bandwidth_kb
|
|
)
|
|
|
|
# Add any one-time referral bonuses
|
|
add_any_referral_bonuses(user, plan_id)
|
|
|
|
# We intentionally skip callbacks on this to ensure the billing plan changes even on invalid users
|
|
user.update_column(:selected_billing_plan_id, related_plan.id)
|
|
|
|
user.subscriptions.create(
|
|
billing_plan: related_plan,
|
|
start_date: DateTime.now,
|
|
end_date: DateTime.now.end_of_day + 10.years
|
|
)
|
|
|
|
user.notifications.create(
|
|
message_html: "<div class='yellow-text text-darken-4'>You signed up for Premium!</div><div>Click here to turn on your Premium pages.</div>",
|
|
icon: 'star',
|
|
icon_color: 'text-darken-3 yellow',
|
|
happened_at: DateTime.current,
|
|
passthrough_link: Rails.application.routes.url_helpers.customization_content_types_path
|
|
) if user.reload.on_premium_plan?
|
|
|
|
report_subscription_change_to_slack(user, plan_id)
|
|
|
|
rescue Stripe::CardError => e
|
|
return :failed_card
|
|
end
|
|
end
|
|
end
|
|
|
|
def self.remove_subscription(user, subscription)
|
|
related_plan = subscription.billing_plan
|
|
|
|
# Remove any bonus bandwidth granted by the plan
|
|
user.update(
|
|
upload_bandwidth_kb: user.upload_bandwidth_kb - related_plan.bonus_bandwidth_kb
|
|
)
|
|
subscription.update(end_date: DateTime.now)
|
|
end
|
|
|
|
def self.cancel_all_existing_subscriptions(user)
|
|
user.update(selected_billing_plan_id: 1)
|
|
user.active_subscriptions.each do |subscription|
|
|
remove_subscription(user, subscription)
|
|
end
|
|
end
|
|
|
|
def self.add_any_referral_bonuses(user, plan_id)
|
|
# This only applies if we're upgrading to premium, obviously
|
|
related_billing_plan = BillingPlan.find_by(stripe_plan_id: plan_id)
|
|
return unless BillingPlan::PREMIUM_IDS.include?(related_billing_plan.id)
|
|
|
|
# If this is the first time this user is subscribing to Premium, gift them (and their referrer, if applicable) extra space
|
|
existing_premium_subscriptions = user.subscriptions.where(billing_plan_id: BillingPlan::PREMIUM_IDS)
|
|
return if existing_premium_subscriptions.any?
|
|
|
|
# 100MB bonus to you
|
|
user.update(
|
|
upload_bandwidth_kb: user.upload_bandwidth_kb + 100_000
|
|
)
|
|
|
|
# 100MB bonus to your referrer
|
|
referring_user = user.referrer
|
|
if referring_user
|
|
referring_user.update(
|
|
upload_bandwidth_kb: referring_user.upload_bandwidth_kb + 100_000
|
|
)
|
|
end
|
|
end
|
|
|
|
def self.available_plans
|
|
BillingPlan.where(available: true)
|
|
end
|
|
|
|
def self.dummy_starter_plan
|
|
BillingPlan.new(name: 'No billing plan', monthly_cents: 0)
|
|
end
|
|
|
|
def self.report_subscription_change_to_slack(user, plan_id)
|
|
return unless Rails.env == 'production'
|
|
|
|
related_plan = BillingPlan.find_by(stripe_plan_id: plan_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 |bp_plan_id, monthly_cents|
|
|
users_on_this_plan = User.where(selected_billing_plan_id: bp_plan_id).count
|
|
total_subscriptions += users_on_this_plan
|
|
monthly_rev_cents += monthly_cents * users_on_this_plan
|
|
end
|
|
|
|
SlackService.post('#subscriptions',
|
|
[
|
|
"Subscription change for #{user.email.split('@').first}@ (##{user.id})",
|
|
"To: *#{related_plan.name}* (#{related_plan.stripe_plan_id}) ($#{related_plan.monthly_cents / 100.0}/month)",
|
|
"#{total_subscriptions} subscriptions total $#{'%.2f' % (monthly_rev_cents / 100)}/mo"
|
|
].join("\n")
|
|
)
|
|
end
|
|
end
|