diff --git a/lib/tasks/subscriptions.rake b/lib/tasks/subscriptions.rake deleted file mode 100644 index 8f47ed1..0000000 --- a/lib/tasks/subscriptions.rake +++ /dev/null @@ -1,103 +0,0 @@ -# frozen_string_literal: true - -require 'stripe' -require 'highline/import' - -desc 'Import subscriptions from Stripe' -task 'subscriptions:import' => :environment do - setup_api - products = get_stripe_products - products_to_import = [] - - products.each do |product| - confirm_import = ask("Do you wish to import product #{product[:name]} (id: #{product[:id]}): (y/N)") - next if confirm_import.downcase != 'y' - products_to_import << product - end - - import_products(products_to_import) - import_subscriptions -end - -def get_stripe_products - puts 'Getting products from Stripe API' - starting_after = nil - products = [] - loop do - results = Stripe::Product.list(limit: 100, starting_after: starting_after) - break if results.data.length == 0 - products = products + results.data - starting_after = results.data.last.id - end - products -end - -def get_stripe_subscriptions - puts 'Getting subscriptions from Stripe API' - starting_after = nil - subscriptions = [] - loop do - results = Stripe::Subscription.list(limit: 100, starting_after: starting_after) - break if results.data.length == 0 - subscriptions = subscriptions + results.data - starting_after = results.data.last.id - end - subscriptions -end - -def import_products(products) - puts 'Importing products' - products.each do |product| - if DiscourseSubscriptions::Product.find_by(external_id: product[:id]).blank? - DiscourseSubscriptions::Product.create(external_id: product[:id]) - end - end -end - -def import_subscriptions - puts 'Importing subscriptions' - product_ids = DiscourseSubscriptions::Product.all.pluck(:external_id) - subscriptions = get_stripe_subscriptions - subscriptions_for_products = subscriptions.select { |sub| product_ids.include?(sub[:items][:data][0][:plan][:product]) } - - subscriptions_for_products.each do |subscription| - product_id = subscription[:items][:data][0][:plan][:product] - customer_id = subscription[:customer] - subscription_id = subscription[:id] - user_id = subscription[:metadata][:user_id].to_i - username = subscription[:metadata][:username] - - if product_id && customer_id && subscription_id - customer = DiscourseSubscriptions::Customer.find_by(user_id: user_id, customer_id: customer_id, product_id: product_id) - - # create the customer record if doesn't exist only if the user_id and username match - # this prevents issues if multiple sites use the same Stripe account - if customer.nil? && user_id && user_id > 0 - user = User.find(user_id) - if user && (user.username == username) - customer = DiscourseSubscriptions::Customer.create( - user_id: user_id, - customer_id: customer_id, - product_id: product_id - ) - end - end - - if customer - if DiscourseSubscriptions::Subscription.find_by(customer_id: customer.id, external_id: subscription_id).blank? - DiscourseSubscriptions::Subscription.create( - customer_id: customer.id, - external_id: subscription_id - ) - end - end - end - end -end - -private - -def setup_api - api_key = SiteSetting.discourse_subscriptions_secret_key || ask('Input Stripe secret key') - Stripe.api_key = api_key -end diff --git a/lib/tasks/subscriptions_import.rake b/lib/tasks/subscriptions_import.rake new file mode 100644 index 0000000..0218388 --- /dev/null +++ b/lib/tasks/subscriptions_import.rake @@ -0,0 +1,168 @@ +# frozen_string_literal: true + +require 'stripe' +require 'highline/import' + +desc 'Import subscriptions from Stripe' +task 'subscriptions:subscriptions_import' => :environment do + setup_api + products = get_stripe_products + strip_products_to_import = [] + + procourse_import = false + procourse_import_response = ask("Were the subscriptions you are importing created in Procourse Memberships?: (y/N)") + if procourse_import_response.downcase != 'y' + procourse_import = true + end + + products.each do |product| + confirm_import = ask("Do you wish to import product #{product[:name]} (id: #{product[:id]}): (y/N)") + next if confirm_import.downcase != 'y' + strip_products_to_import << product + end + + import_products(strip_products_to_import) + import_subscriptions(procourse_import) +end + +def get_stripe_products(starting_after: nil) + puts 'Getting products from Stripe API' + + all_products = [] + + loop do + products = Stripe::Product.list({ type: 'service', starting_after: starting_after, active: true }) + all_products += products[:data] + break if products[:has_more] == false + starting_after = products[:data].last["id"] + end + + all_products + +end + +def get_stripe_subscriptions(starting_after: nil) + puts 'Getting Subscriptions from Stripe API' + + all_subscriptions = [] + + loop do + subscriptions = Stripe::Subscription.list({ starting_after: starting_after, status: 'active' }) + all_subscriptions += subscriptions[:data] + break if subscriptions[:has_more] == false + starting_after = subscriptions[:data].last["id"] + end + + all_subscriptions +end + +def get_stripe_customers(starting_after: nil) + puts 'Getting Customers from Stripe API' + + all_customers = [] + + loop do + customers = Stripe::Customer.list({ starting_after: starting_after }) + all_customers += customers[:data] + break if customers[:has_more] == false + starting_after = customers[:data].last["id"] + end + + all_customers +end + +def import_products(products) + puts 'Importing products:' + + products.each do |product| + puts "Looking for external_id #{product[:id]} ..." + if DiscourseSubscriptions::Product.find_by(external_id: product[:id]).blank? + DiscourseSubscriptions::Product.create(external_id: product[:id]) + puts "Subscriptions Product external_id: #{product[:id]} CREATED" + else + puts "Subscriptions Product external_id: #{product[:id]} already exists" + end + end +end + +def import_subscriptions(procourse_import) + puts 'Importing subscriptions' + product_ids = DiscourseSubscriptions::Product.all.pluck(:external_id) + + all_customers = get_stripe_customers + puts "Total available Stripe Customers: #{all_customers.length.to_s}, the first of which is customer id: #{all_customers[0][:description]}" + + subscriptions = get_stripe_subscriptions + puts "Total Active Subscriptions available: #{subscriptions.length.to_s}" + + subscriptions_for_products = subscriptions.select { |sub| product_ids.include?(sub[:items][:data][0][:price][:product]) } + puts "Total Subscriptions matching Products to Import: #{subscriptions_for_products.length.to_s}" + + subscriptions_for_products.each do |subscription| + product_id = subscription[:items][:data][0][:plan][:product] + customer_id = subscription[:customer] + subscription_id = subscription[:id] + + if procourse_import + stripe_customer = all_customers.select { |cust| cust[:id] == customer_id } + user_id = stripe_customer[0][:description].to_i + username = nil + else + user_id = subscription[:metadata][:user_id].to_i + username = subscription[:metadata][:username] + end + + if product_id && customer_id && subscription_id + subscriptions_customer = DiscourseSubscriptions::Customer.find_by(user_id: user_id, customer_id: customer_id, product_id: product_id) + + if subscriptions_customer.nil? && user_id && user_id > 0 + # create the customer record if doesn't exist only if the user_id and username match, which + # prevents issues if multiple sites use the same Stripe account. Does not apply to a Procourse import. + user = User.find(user_id) + if procourse_import || (user && (user.username == username)) + subscriptions_customer = DiscourseSubscriptions::Customer.create( + user_id: user_id, + customer_id: customer_id, + product_id: product_id + ) + puts "Subscriptions Customer user_id: #{user_id}, customer_id: #{customer_id}, product_id: #{product_id}) CREATED" + end + else + puts "Subscriptions Customer user_id: #{user_id}, customer_id: #{customer_id}, product_id: #{product_id}) already exists" + end + + if subscriptions_customer + if DiscourseSubscriptions::Subscription.find_by(customer_id: subscriptions_customer.id, external_id: subscription_id).blank? + DiscourseSubscriptions::Subscription.create( + customer_id: subscriptions_customer.id, + external_id: subscription_id + ) + puts "Discourse Subscription customer_id: #{subscriptions_customer.id}, external_id: #{subscription_id}) CREATED" + else + puts "Discourse Subscription customer_id: #{subscriptions_customer.id}, external_id: #{subscription_id}) already exists" + end + + if procourse_import + # Update Procourse Stripe data as it would be if it were created by discourse_subscriptions + discourse_user = User.find(user_id) + puts "Discourse User: #{discourse_user.username_lower} found for Strip metadata update ..." + + updated_subsciption = Stripe::Subscription.update(subscription_id, + { metadata: { user_id: user_id, + username: discourse_user.username_lower } }) + puts "Stripe Subscription: #{updated_subsciption[:id]}, metadata: #{updated_subsciption[:metadata]} UPDATED" + + updated_customer = Stripe::Customer.update(customer_id, { email: discourse_user.email }) + puts "Stripe Customer: #{updated_customer[:id]}, email: #{updated_customer[:email]} UPDATED" + end + end + end + end +end + +private + +def setup_api + api_key = SiteSetting.discourse_subscriptions_secret_key || ask('Input Stripe secret key') + Stripe.api_key = api_key +end