Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stripe prices #8424

Draft
wants to merge 3 commits into
base: stripe-prices-refactor
Choose a base branch
from
Draft
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
6 changes: 3 additions & 3 deletions app/controllers/alaveteli_pro/plans_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ class AlaveteliPro::PlansController < AlaveteliPro::BaseController
before_action :authenticate, :check_has_current_subscription, only: [:show]

def index
@plans = AlaveteliPro::Plan.list
@prices = AlaveteliPro::Price.list
@pro_site_name = pro_site_name
end

def show
@plan = AlaveteliPro::Plan.retrieve(params[:id])
@plan || raise(ActiveRecord::RecordNotFound)
@price = AlaveteliPro::Price.retrieve(params[:id])
@price || raise(ActiveRecord::RecordNotFound)
end

private
Expand Down
18 changes: 9 additions & 9 deletions app/controllers/alaveteli_pro/subscriptions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class AlaveteliPro::SubscriptionsController < AlaveteliPro::BaseController

before_action :check_allowed_to_subscribe_to_pro, only: [:create]
before_action :prevent_duplicate_submission, only: [:create]
before_action :load_plan, :load_coupon, only: [:create]
before_action :load_price, :load_coupon, only: [:create]

def index
@customer = current_user.pro_account.try(:stripe_customer)
Expand All @@ -28,8 +28,8 @@ def create
@pro_account.update_stripe_customer

attributes = {
plan: @plan.id,
tax_percent: @plan.tax_percent,
items: [{ price: @price.id }],
tax_percent: @price.tax_percent,
payment_behavior: 'allow_incomplete'
}
attributes[:coupon] = @coupon.id if @coupon
Expand Down Expand Up @@ -62,7 +62,7 @@ def create
end

if flash[:error]
json_redirect_to plan_path(@plan)
json_redirect_to plan_path(@price)
else
redirect_to authorise_subscription_path(@subscription.id)
end
Expand All @@ -89,7 +89,7 @@ def authorise
flash[:error] = _('There was a problem authorising your payment. You ' \
'have not been charged. Please try again.')

json_redirect_to plan_path(@subscription.plan)
json_redirect_to plan_path(@subscription.price)

elsif @subscription.active?
current_user.add_role(:pro)
Expand Down Expand Up @@ -168,16 +168,16 @@ def check_allowed_to_subscribe_to_pro
end

def check_has_current_subscription
# TODO: This doesn't take the plan in to account
# TODO: This doesn't take the price in to account
return if @user.pro_account.try(:subscription?)

flash[:notice] = _("You don't currently have a Pro subscription")
redirect_to pro_plans_path
end

def load_plan
@plan = AlaveteliPro::Plan.retrieve(params[:plan_id])
@plan || redirect_to(pro_plans_path)
def load_price
@price = AlaveteliPro::Price.retrieve(params[:price_id])
@price || redirect_to(pro_plans_path)
end

def load_coupon
Expand Down
6 changes: 4 additions & 2 deletions app/controllers/concerns/alaveteli_pro/stripe_namespace.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
module AlaveteliPro::StripeNamespace
extend ActiveSupport::Concern

def add_stripe_namespace(string)
def add_stripe_namespace(string, prefix: nil)
return string if namespace.blank?
return string if prefix && string.start_with?(/#{prefix}_/)
return string if string.start_with?(/#{namespace}-/)

[namespace, string].join('-')
end

def remove_stripe_namespace(string)
def remove_stripe_namespace(string, prefix: nil)
return string if namespace.blank?
return string if prefix && string.start_with?(/#{prefix}_/)
return string unless string.start_with?(/#{namespace}-/)

string.sub(/^#{namespace}-/, '')
Expand Down
45 changes: 0 additions & 45 deletions app/helpers/alaveteli_pro/plan_helper.rb

This file was deleted.

45 changes: 45 additions & 0 deletions app/helpers/alaveteli_pro/price_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
##
# Helper methods for formatting and displaying billing and price information
# in the Alaveteli Pro interface
#
module AlaveteliPro::PriceHelper
def billing_frequency(price)
if interval(price) == 'day' && interval_count(price) == 1
_('Billed: Daily')
elsif interval(price) == 'week' && interval_count(price) == 1
_('Billed: Weekly')
elsif interval(price) == 'month' && interval_count(price) == 1
_('Billed: Monthly')
elsif interval(price) == 'year' && interval_count(price) == 1
_('Billed: Annually')
else
_('Billed: every {{interval}}', interval: interval(price))
end
end

def billing_interval(price)
if interval_count(price) == 1
_('per user, per {{interval}}', interval: pluralize_interval(price))
else
_('per user, every {{interval}}', interval: pluralize_interval(price))
end
end

private

def pluralize_interval(price)
count = interval_count(price)
interval = interval(price)
return interval if count == 1

pluralize(count, interval)
end

def interval(price)
price.recurring['interval']
end

def interval_count(price)
price.recurring['interval_count']
end
end
32 changes: 0 additions & 32 deletions app/models/alaveteli_pro/plan.rb

This file was deleted.

37 changes: 37 additions & 0 deletions app/models/alaveteli_pro/price.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
##
# A wrapper for a Stripe::Price
#
class AlaveteliPro::Price < SimpleDelegator
extend AlaveteliPro::StripeNamespace
include AlaveteliPro::StripeNamespace
include Taxable

tax :unit_amount

def self.list
AlaveteliConfiguration.stripe_prices.inject([]) do |arr, (_, id)|
arr << retrieve(id)
arr
end
end

def self.retrieve(id)
new(Stripe::Price.retrieve(add_stripe_namespace(id, prefix: 'price')))
end

def to_param
AlaveteliConfiguration.stripe_prices[id]
end

def ===(other)
self.id == other.id

Check warning on line 27 in app/models/alaveteli_pro/price.rb

View workflow job for this annotation

GitHub Actions / build

[rubocop] reported by reviewdog 🐶 Redundant `self` detected. (https://rubystyle.guide#no-self-unless-required) Raw Output: app/models/alaveteli_pro/price.rb:27:5: C: Style/RedundantSelf: Redundant `self` detected. (https://rubystyle.guide#no-self-unless-required)
end

# product
def product
@product ||= (
product_id = __getobj__.product
Stripe::Product.retrieve(product_id) if product_id
)
end
end
6 changes: 3 additions & 3 deletions app/models/alaveteli_pro/subscription.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ def delete
Stripe::Subscription.cancel(id)
end

# plan
def plan
@plan ||= AlaveteliPro::Plan.new(__getobj__.plan)
# price
def price
@price ||= AlaveteliPro::Price.new(items.first.price)
end

private
Expand Down
8 changes: 4 additions & 4 deletions app/views/alaveteli_pro/plans/_pricing_tiers.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="pricing__tiers">
<% @plans.each do |plan| %>
<% @prices.each do |price| %>
<div class="pricing__tier pricing__tier--primary">
<div class="pricing__tier__heading">
<h2><%= _('Professional') %></h2>
Expand All @@ -10,10 +10,10 @@

<p class="price-label">
<span class="price-label__amount">
<%= format_currency(plan.amount_with_tax, no_cents_if_whole: true) %>
<%= format_currency(price.unit_amount_with_tax, no_cents_if_whole: true) %>
</span>

<%= billing_interval(plan) %>
<%= billing_interval(price) %>
</p>
</div>

Expand All @@ -27,7 +27,7 @@
<li><%= _('Friendly support') %></li>
</ul>

<%= link_to _('Sign up'), plan_path(plan), class: 'button button-pop' %>
<%= link_to _('Sign up'), plan_path(price), class: 'button button-pop' %>
</div>
</div>
<% end %>
Expand Down
8 changes: 4 additions & 4 deletions app/views/alaveteli_pro/plans/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@
<h3><%= _('Selected plan') %></h3>
<div class="plan-overview">
<div class="plan-overview__desc">
<%= @plan.product.name %>
<%= @price.product.name %>
</div>
<div class="plan-overview__amount">
<%= format_currency(@plan.amount_with_tax) %>
<%= billing_frequency(@plan) %>
<%= format_currency(@price.unit_amount_with_tax) %>
<%= billing_frequency(@price) %>
</div>
</div>
</div>
Expand Down Expand Up @@ -65,7 +65,7 @@
</div>

<div class="settings__section">
<%= hidden_field_tag 'plan_id', @plan.id %>
<%= hidden_field_tag 'price_id', @price.id %>
<%= submit_tag _('Subscribe'), id: 'js-stripe-submit', disabled: true, data: { disable_with: 'Processing...' } %>
<%= link_to _('Cancel'), pro_plans_path, class: 'settings__cancel-button' %>
<p id="card-errors"></p>
Expand Down
6 changes: 3 additions & 3 deletions app/views/alaveteli_pro/subscriptions/_subscription.html.erb
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@

<div class="plan-overview">
<div class="plan-overview__desc">
<%= subscription.plan.product.name %>
<%= subscription.price.product.name %>
</div>

<div class="plan-overview__amount">
<%= format_currency(subscription.plan.amount_with_tax) %>
<%= billing_frequency(subscription.plan) %>
<%= format_currency(subscription.price.unit_amount_with_tax) %>
<%= billing_frequency(subscription.price) %>
<% if subscription.discounted? %>
<br>
<%= _('<strong>{{discounted_amount}}</strong> with discount ' \
Expand Down
15 changes: 15 additions & 0 deletions config/general.yml-example
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,21 @@ STRIPE_SECRET_KEY: ''
# ---
STRIPE_NAMESPACE: ''

# List of Stripe Prices which if a user signs up to will grant them access to
# Alaveteli Pro. Rendered on the Pro pricing pages in the order defined here.
#
# STRIPE_PRICES - Hash of objects with key equla to the Stripe Price IDs as the
# value equal to parameterise short human readable string
#
# Examples:
#
# STRIPE_PRICES:
# price_123: pro
# price:456: pro-annual-billing
#
# ---
STRIPE_PRICES: []

# Stripe.com webhook secret. Only required for Alaveteli Pro.
#
# STRIPE_WEBHOOK_SECRET: - String (default: '')
Expand Down
9 changes: 8 additions & 1 deletion lib/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ module AlaveteliConfiguration
SMTP_MAILER_PORT: 25,
SMTP_MAILER_USER_NAME: '',
STRIPE_NAMESPACE: '',
STRIPE_PRICES: {},
STRIPE_PUBLISHABLE_KEY: '',
STRIPE_SECRET_KEY: '',
STRIPE_TAX_RATE: '0.20',
Expand Down Expand Up @@ -145,7 +146,13 @@ def self.get(key, default)
def self.method_missing(name)
key = name.to_s.upcase
if DEFAULTS.key?(key.to_sym)
get(key, DEFAULTS[key.to_sym])
value = get(key, DEFAULTS[key.to_sym])
case value
when Hash
value.with_indifferent_access
else
value
end
else
super
end
Expand Down
Loading
Loading