Skip to content

Commit

Permalink
Add insider discounts (#7150)
Browse files Browse the repository at this point in the history
* Add insider discounts

* Prepare stripe for 100% off coupons

* Remove typo
  • Loading branch information
iHiD authored Nov 8, 2024
1 parent 9272e8b commit 1fcb484
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 1 deletion.
34 changes: 34 additions & 0 deletions app/commands/user/generate_bootcamp_affiliate_coupon_code.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
class User::GenerateBootcampAffiliateCouponCode
include Mandate

initialize_with :user

def call
# Easy cheap guard
return if user_data.bootcamp_affiliate_coupon_code.present?

# Now things get expensive with Stripe call and lock below
code = generate_coupon_code
user_data.with_lock do
return if user_data.bootcamp_affiliate_coupon_code.present?

user_data.update!(bootcamp_affiliate_coupon_code: code)
end
end

private
delegate :data, to: :user, prefix: true

memoize
def generate_coupon_code
promo_code = Stripe::PromotionCode.create(
coupon: COUPON_ID,
metadata: {
user_id: user.id
}
)
promo_code.code
end

COUPON_ID = "NRp5SOVV".freeze
end
35 changes: 35 additions & 0 deletions app/commands/user/generate_bootcamp_free_coupon_code.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
class User::GenerateBootcampFreeCouponCode
include Mandate

initialize_with :user

def call
# Easy cheap guard
return if user_data.bootcamp_free_coupon_code.present?

# Now things get expensive with Stripe call and lock below
code = generate_coupon_code
user_data.with_lock do
return if user_data.bootcamp_free_coupon_code.present?

user_data.update!(bootcamp_free_coupon_code: code)
end
end

private
delegate :data, to: :user, prefix: true

memoize
def generate_coupon_code
promo_code = Stripe::PromotionCode.create(
coupon: COUPON_ID,
max_redemptions: 1,
metadata: {
user_id: user.id
}
)
promo_code.code
end

COUPON_ID = "OarhoKrd".freeze
end
1 change: 1 addition & 0 deletions app/controllers/bootcamp_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def stripe_create_checkout_session
session = Stripe::Checkout::Session.create({
ui_mode: 'embedded',
customer_email: @bootcamp_data.email,
customer_creation: "always",
line_items: [{
price: stripe_price,
quantity: 1
Expand Down
1 change: 1 addition & 0 deletions config/initializers/stripe.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require 'stripe'

Stripe.api_key = Exercism.secrets.stripe_secret_key
Stripe.api_version = '2024-10-28.acacia'
8 changes: 8 additions & 0 deletions db/migrate/20241108083100_add_insider_discounts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class AddInsiderDiscounts < ActiveRecord::Migration[7.0]
def change
return if Rails.env.production?

add_column :user_data, :bootcamp_affiliate_coupon_code, :string, null: true
add_column :user_data, :bootcamp_free_coupon_code, :string, null: true
end
end
4 changes: 3 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2024_11_07_133957) do
ActiveRecord::Schema[7.0].define(version: 2024_11_08_083100) do
create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
Expand Down Expand Up @@ -1390,6 +1390,8 @@
t.datetime "premium_until"
t.boolean "trainer", default: false, null: false
t.integer "seniority", limit: 1
t.string "bootcamp_affiliate_coupon_code"
t.string "bootcamp_free_coupon_code"
t.index ["discord_uid"], name: "index_user_data_on_discord_uid", unique: true
t.index ["first_donated_at", "show_on_supporters_page", "user_id"], name: "index_user_data__supporters-page"
t.index ["first_donated_at"], name: "index_user_data_on_first_donated_at"
Expand Down
25 changes: 25 additions & 0 deletions test/models/user/generate_bootcamp_affiliate_coupon_code_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require "test_helper"

class User::GenerateBootcampAffiliateCouponCodeTest < ActiveSupport::TestCase
test "creates correctly" do
user = create :user
code = SecureRandom.hex(6)
Stripe::PromotionCode.expects(:create).with(
coupon: "NRp5SOVV", metadata: { user_id: user.id }
).returns(OpenStruct.new(code:))

User::GenerateBootcampAffiliateCouponCode.(user)

assert_equal code, user.bootcamp_affiliate_coupon_code
end

test "immutable" do
code = SecureRandom.hex(6)
user = create :user, bootcamp_affiliate_coupon_code: code
Stripe::PromotionCode.expects(:create).never

User::GenerateBootcampAffiliateCouponCode.(user)

assert_equal code, user.bootcamp_affiliate_coupon_code
end
end
27 changes: 27 additions & 0 deletions test/models/user/generate_bootcamp_free_coupon_code_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require "test_helper"

class User::GenerateBootcampFreeCouponCodeTest < ActiveSupport::TestCase
test "creates correctly" do
user = create :user
code = SecureRandom.hex(6)
Stripe::PromotionCode.expects(:create).with(
coupon: "OarhoKrd",
max_redemptions: 1,
metadata: { user_id: user.id }
).returns(OpenStruct.new(code:))

User::GenerateBootcampFreeCouponCode.(user)

assert_equal code, user.bootcamp_free_coupon_code
end

test "immutable" do
code = SecureRandom.hex(6)
user = create :user, bootcamp_free_coupon_code: code
Stripe::PromotionCode.expects(:create).never

User::GenerateBootcampFreeCouponCode.(user)

assert_equal code, user.bootcamp_free_coupon_code
end
end

0 comments on commit 1fcb484

Please sign in to comment.