koudoku 1.2.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/app/concerns/koudoku/subscription.rb +15 -17
  4. data/app/controllers/koudoku/application_controller.rb +0 -1
  5. data/app/controllers/koudoku/subscriptions_controller.rb +39 -29
  6. data/app/helpers/koudoku/application_helper.rb +4 -16
  7. data/app/views/koudoku/subscriptions/_card.html.erb +6 -6
  8. data/app/views/koudoku/subscriptions/_pricing_table.html.erb +4 -4
  9. data/app/views/koudoku/subscriptions/_social_proof.html.erb +3 -3
  10. data/app/views/koudoku/subscriptions/edit.html.erb +3 -3
  11. data/app/views/koudoku/subscriptions/index.html.erb +1 -1
  12. data/app/views/koudoku/subscriptions/new.html.erb +1 -1
  13. data/app/views/koudoku/subscriptions/show.html.erb +9 -9
  14. data/app/views/koudoku/subscriptions/unauthorized.html.erb +1 -1
  15. data/config/locales/en.yml +58 -0
  16. data/config/locales/pt-BR.yml +57 -0
  17. data/lib/generators/koudoku/templates/app/models/subscription.rb +1 -1
  18. data/lib/generators/koudoku/templates/config/initializers/koudoku.rb +6 -6
  19. data/lib/koudoku.rb +23 -15
  20. data/lib/koudoku/errors.rb +4 -0
  21. data/lib/koudoku/version.rb +1 -1
  22. data/spec/dummy/db/development.sqlite3 +0 -0
  23. data/spec/dummy/db/migrate/20130318201927_create_customers.rb +1 -1
  24. data/spec/dummy/db/migrate/20130318204455_create_subscriptions.rb +1 -1
  25. data/spec/dummy/db/migrate/20130318204458_create_plans.rb +1 -1
  26. data/spec/dummy/db/migrate/20130318204502_create_coupons.rb +1 -1
  27. data/spec/dummy/db/migrate/20130520163946_add_interval_to_plan.rb +1 -1
  28. data/spec/dummy/db/schema.rb +31 -32
  29. data/spec/dummy/db/test.sqlite3 +0 -0
  30. data/spec/dummy/log/development.log +0 -0
  31. data/spec/dummy/log/test.log +0 -0
  32. metadata +6 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c55236ebdacad52170e7ef4bdad84228bcb7ce4c
4
- data.tar.gz: cd3b6afee90283f84752587b67875432323db894
3
+ metadata.gz: bdd41d4b7982cbd59644cc114087f962a5d48158
4
+ data.tar.gz: c4d967213e7fb9e116147eb01a63ecf842546e2a
5
5
  SHA512:
6
- metadata.gz: 87ce48f1f83e034e273302a4b9fbbcb1349183109edceca84eb654b22ef4da7ee2c395fa279feebc2d9754c38cbdd6163cc3d03baca1c72d6fbe6927e71a80fd
7
- data.tar.gz: 916d481ef9817bc6ddefd58e743a4ae3d28897ba11b033b66134a9595d5f4efda62c25d604cc78abfd241310e19cc752efdd656ca9faa39bb57fa93113511f0e
6
+ metadata.gz: debb34bd494f7141f49d8fc6f2814e7ff68bfdc6a32d566ec9d9fd12aab35a96aa8f5eb7b176c14213f973fca6afca1332c378957a09364a630567dd9b6e1b4e
7
+ data.tar.gz: aec0b3c780f520c04a9154f199ebdcb724e5d38d92fe456c57ec47c8db1f73e99ddfcb9132de5db8fe45eef24b90862ef153ff1f38a6c6d0f31c4a7f712ec3aa
data/README.md CHANGED
@@ -33,6 +33,8 @@ Add the following to `app/views/layouts/application.html.erb` before your `<head
33
33
 
34
34
  After installing, you'll need to add some subscription plans. (You can see an explanation of each of the attributes in the table below.)
35
35
 
36
+ **Note:** You need to create the plans in your [Stripe Dashboard](https://dashboard.stripe.com) separately.
37
+
36
38
  ```ruby
37
39
  Plan.create({
38
40
  name: 'Personal',
@@ -7,7 +7,7 @@ module Koudoku::Subscription
7
7
  # client-side after storing the credit card information.
8
8
  attr_accessor :credit_card_token
9
9
 
10
- belongs_to :plan
10
+ belongs_to :plan, optional: true
11
11
 
12
12
  # update details.
13
13
  before_save :processing!
@@ -66,7 +66,7 @@ module Koudoku::Subscription
66
66
  prepare_for_upgrade
67
67
 
68
68
  begin
69
-
69
+ raise Koudoku::NilCardToken, "No card token received. Check for JavaScript errors breaking Stripe.js on the previous page." unless credit_card_token.present?
70
70
  customer_attributes = {
71
71
  description: subscription_owner_description,
72
72
  email: subscription_owner_email,
@@ -79,8 +79,8 @@ module Koudoku::Subscription
79
79
  customer_attributes[:trial_end] = coupon.free_trial_ends.to_i
80
80
  end
81
81
  end
82
-
83
- customer_attributes[:coupon] = @coupon_code if @coupon_code
82
+
83
+ customer_attributes[:coupon] = @coupon_code if @coupon_code
84
84
 
85
85
  # create a customer at that package level.
86
86
  customer = Stripe::Customer.create(customer_attributes)
@@ -96,7 +96,7 @@ module Koudoku::Subscription
96
96
 
97
97
  # store the customer id.
98
98
  self.stripe_id = customer.id
99
- self.last_four = customer.cards.retrieve(customer.default_card).last4
99
+ self.last_four = customer.sources.retrieve(customer.default_source).last4
100
100
 
101
101
  finalize_new_subscription!
102
102
  finalize_upgrade!
@@ -123,40 +123,38 @@ module Koudoku::Subscription
123
123
 
124
124
  # fetch the customer.
125
125
  customer = Stripe::Customer.retrieve(self.stripe_id)
126
- customer.card = self.credit_card_token
126
+ customer.source = self.credit_card_token
127
127
  customer.save
128
128
 
129
129
  # update the last four based on this new card.
130
- self.last_four = customer.cards.retrieve(customer.default_card).last4
130
+ self.last_four = customer.sources.retrieve(customer.default_source).last4
131
131
  finalize_card_update!
132
132
 
133
133
  end
134
-
135
134
  end
136
-
137
135
  end
138
-
139
-
136
+
137
+
140
138
  def describe_difference(plan_to_describe)
141
139
  if plan.nil?
142
140
  if persisted?
143
- "Upgrade"
141
+ I18n.t('koudoku.plan_difference.upgrade')
144
142
  else
145
143
  if Koudoku.free_trial?
146
- "Start Trial"
144
+ I18n.t('koudoku.plan_difference.start_trial')
147
145
  else
148
- "Upgrade"
146
+ I18n.t('koudoku.plan_difference.upgrade')
149
147
  end
150
148
  end
151
149
  else
152
150
  if plan_to_describe.is_upgrade_from?(plan)
153
- "Upgrade"
151
+ I18n.t('koudoku.plan_difference.upgrade')
154
152
  else
155
- "Downgrade"
153
+ I18n.t('koudoku.plan_difference.downgrade')
156
154
  end
157
155
  end
158
156
  end
159
-
157
+
160
158
  # Set a Stripe coupon code that will be used when a new Stripe customer (a.k.a. Koudoku subscription)
161
159
  # is created
162
160
  def coupon_code=(new_code)
@@ -2,6 +2,5 @@ module Koudoku
2
2
  class ApplicationController < ::ApplicationController
3
3
  layout Koudoku.layout
4
4
  helper :application
5
-
6
5
  end
7
6
  end
@@ -1,12 +1,12 @@
1
1
  module Koudoku
2
2
  class SubscriptionsController < ApplicationController
3
- before_filter :load_owner
4
- before_filter :show_existing_subscription, only: [:index, :new, :create], unless: :no_owner?
5
- before_filter :load_subscription, only: [:show, :cancel, :edit, :update]
6
- before_filter :load_plans, only: [:index, :edit]
3
+ before_action :load_owner
4
+ before_action :show_existing_subscription, only: [:index, :new, :create], unless: :no_owner?
5
+ before_action :load_subscription, only: [:show, :cancel, :edit, :update]
6
+ before_action :load_plans, only: [:index, :edit]
7
7
 
8
8
  def load_plans
9
- @plans = ::Plan.order(:price)
9
+ @plans = ::Plan.order(:display_order)
10
10
  end
11
11
 
12
12
  def unauthorized
@@ -17,13 +17,14 @@ module Koudoku
17
17
  def load_owner
18
18
  unless params[:owner_id].nil?
19
19
  if current_owner.present?
20
-
20
+
21
21
  # we need to try and look this owner up via the find method so that we're
22
22
  # taking advantage of any override of the find method that would be provided
23
23
  # by older versions of friendly_id. (support for newer versions default behavior
24
24
  # below.)
25
+
25
26
  searched_owner = current_owner.class.find(params[:owner_id]) rescue nil
26
-
27
+
27
28
  # if we couldn't find them that way, check whether there is a new version of
28
29
  # friendly_id in place that we can use to look them up by their slug.
29
30
  # in christoph's words, "why?!" in my words, "warum?!!!"
@@ -31,7 +32,7 @@ module Koudoku
31
32
  if searched_owner.nil? && current_owner.class.respond_to?(:friendly)
32
33
  searched_owner = current_owner.class.friendly.find(params[:owner_id]) rescue nil
33
34
  end
34
-
35
+
35
36
  if current_owner.try(:id) == searched_owner.try(:id)
36
37
  @owner = current_owner
37
38
  else
@@ -50,21 +51,32 @@ module Koudoku
50
51
  def load_subscription
51
52
  ownership_attribute = :"#{Koudoku.subscriptions_owned_by}_id"
52
53
  @subscription = ::Subscription.where(ownership_attribute => current_owner.id).find_by_id(params[:id])
54
+
55
+ # also, if cancan methods are available, we should use that to authorize.
56
+ if defined?(:can?)
57
+ return unauthorized unless can? :manage, @subscription
58
+ end
59
+
53
60
  return @subscription.present? ? @subscription : unauthorized
54
61
  end
55
62
 
56
- # the following two methods allow us to show the pricing table before someone has an account.
63
+ # the following three methods allow us to show the pricing table before someone has an account.
57
64
  # by default these support devise, but they can be overriden to support others.
58
65
  def current_owner
59
66
  # e.g. "self.current_user"
60
67
  send "current_#{Koudoku.subscriptions_owned_by}"
61
68
  end
62
69
 
70
+ def current_owned_through_or_by
71
+ # e.g. "self.current_user"
72
+ send "current_#{Koudoku.subscriptions_owned_through_or_by}"
73
+ end
74
+
63
75
  def redirect_to_sign_up
64
76
  # this is a Devise default variable and thus should not change its name
65
- # when we change subscription owners from :user to :company
66
- session["user_return_to"] = new_subscription_path(plan: params[:plan])
67
- redirect_to new_registration_path(Koudoku.subscriptions_owned_by.to_s)
77
+ # when we change subscription owners from :user to :company
78
+ session["#{Koudoku.subscriptions_owned_through_or_by}_return_to"] = new_subscription_path(plan: params[:plan])
79
+ redirect_to new_registration_path(Koudoku.subscriptions_owned_through_or_by.to_s)
68
80
  end
69
81
 
70
82
  def index
@@ -74,9 +86,6 @@ module Koudoku
74
86
  redirect_to koudoku.edit_owner_subscription_path(current_owner, current_owner.subscription)
75
87
  end
76
88
 
77
- # Load all plans.
78
- @plans = ::Plan.order(:display_order).all
79
-
80
89
  # Don't prep a subscription unless a user is authenticated.
81
90
  unless no_owner?
82
91
  # we should also set the owner of the subscription here.
@@ -97,9 +106,9 @@ module Koudoku
97
106
  else
98
107
  redirect_to_sign_up
99
108
  end
100
-
109
+
101
110
  else
102
- raise "This feature depends on Devise for authentication."
111
+ raise I18n.t('koudoku.failure.feature_depends_on_devise')
103
112
  end
104
113
 
105
114
  else
@@ -115,15 +124,16 @@ module Koudoku
115
124
  end
116
125
 
117
126
  def create
127
+
118
128
  @subscription = ::Subscription.new(subscription_params)
119
129
  @subscription.subscription_owner = @owner
120
130
  @subscription.coupon_code = session[:koudoku_coupon_code]
121
-
131
+
122
132
  if @subscription.save
123
133
  flash[:notice] = after_new_subscription_message
124
- redirect_to after_new_subscription_path
134
+ redirect_to after_new_subscription_path
125
135
  else
126
- flash[:error] = 'There was a problem processing this transaction.'
136
+ flash[:error] = I18n.t('koudoku.failure.problem_processing_transaction')
127
137
  render :new
128
138
  end
129
139
  end
@@ -132,7 +142,7 @@ module Koudoku
132
142
  end
133
143
 
134
144
  def cancel
135
- flash[:notice] = "You've successfully cancelled your subscription."
145
+ flash[:notice] = I18n.t('koudoku.confirmations.subscription_cancelled')
136
146
  @subscription.plan_id = nil
137
147
  @subscription.save
138
148
  redirect_to owner_subscription_path(@owner, @subscription)
@@ -143,17 +153,17 @@ module Koudoku
143
153
 
144
154
  def update
145
155
  if @subscription.update_attributes(subscription_params)
146
- flash[:notice] = "You've successfully updated your subscription."
156
+ flash[:notice] = I18n.t('koudoku.confirmations.subscription_updated')
147
157
  redirect_to owner_subscription_path(@owner, @subscription)
148
158
  else
149
- flash[:error] = 'There was a problem processing this transaction.'
159
+ flash[:error] = I18n.t('koudoku.failure.problem_processing_transaction')
150
160
  render :edit
151
161
  end
152
162
  end
153
163
 
154
164
  private
155
165
  def subscription_params
156
-
166
+
157
167
  # If strong_parameters is around, use that.
158
168
  if defined?(ActionController::StrongParameters)
159
169
  params.require(:subscription).permit(:plan_id, :stripe_id, :current_price, :credit_card_token, :card_type, :last_four)
@@ -163,17 +173,17 @@ module Koudoku
163
173
  end
164
174
 
165
175
  end
166
-
176
+
167
177
  def after_new_subscription_path
168
178
  return super(@owner, @subscription) if defined?(super)
169
179
  owner_subscription_path(@owner, @subscription)
170
180
  end
171
-
181
+
172
182
  def after_new_subscription_message
173
183
  controller = ::ApplicationController.new
174
- controller.respond_to?(:new_subscription_notice_message) ?
175
- controller.try(:new_subscription_notice_message) :
176
- "You've been successfully upgraded."
184
+ controller.respond_to?(:new_subscription_notice_message) ?
185
+ controller.try(:new_subscription_notice_message) :
186
+ I18n.t('koudoku.confirmations.subscription_upgraded')
177
187
  end
178
188
  end
179
189
  end
@@ -6,26 +6,14 @@ module Koudoku
6
6
  end
7
7
 
8
8
  def plan_interval(plan)
9
- case plan.interval
10
- when "month"
11
- "month"
12
- when "year"
13
- "year"
14
- when "week"
15
- "week"
16
- when "6-month"
17
- "half-year"
18
- when "3-month"
19
- "quarter"
20
- else
21
- "month"
22
- end
9
+ interval = %w(month year week 6-month 3-month).include?(plan.interval) ? plan.interval.delete('-') : 'month'
10
+ I18n.t("koudoku.plan_intervals.#{interval}")
23
11
  end
24
-
12
+
25
13
  # returns TRUE if the controller belongs to Koudoku
26
14
  # false in all other cases, for convenience when executing filters
27
15
  # in the main application
28
- def koudoku_controller?
16
+ def koudoku_controller?
29
17
  is_a? Koudoku::ApplicationController
30
18
  end
31
19
  end
@@ -9,14 +9,14 @@
9
9
  <legend><%= title %></legend>
10
10
 
11
11
  <div class="control-group">
12
- <label class="control-label">Card Number</label>
12
+ <label class="control-label"><%= t('koudoku.payment.card_number') %></label>
13
13
  <div class="controls">
14
14
  <input type="text" size="20" autocomplete="off" class="card-number"/>
15
15
  </div>
16
16
  </div>
17
17
 
18
18
  <div class="control-group">
19
- <label class="control-label">Expiration (MM/YYYY)</label>
19
+ <label class="control-label"><%= t('koudoku.payment.expiration') %></label>
20
20
  <div class="controls">
21
21
  <input type="text" size="2" class="card-expiry-month input-mini"/>
22
22
  <span> / </span>
@@ -25,7 +25,7 @@
25
25
  </div>
26
26
 
27
27
  <div class="control-group">
28
- <label class="control-label">CVC</label>
28
+ <label class="control-label"><%= t('koudoku.payment.cvc') %></label>
29
29
  <div class="controls">
30
30
  <input type="text" size="4" autocomplete="off" class="card-cvc input-small"/>
31
31
  </div>
@@ -39,11 +39,11 @@
39
39
  <div class="control-group">
40
40
  <div class="controls">
41
41
  <% if Koudoku.free_trial? %>
42
- <button type="submit" class="btn btn-primary submit-button">Save Billing Information</button>
42
+ <button type="submit" class="btn btn-primary submit-button"><%= t('koudoku.payment.save_billing_info') %></button>
43
43
  <% else %>
44
- <button type="submit" class="btn btn-primary submit-button">Upgrade Your Account</button>
44
+ <button type="submit" class="btn btn-primary submit-button"><%= t('koudoku.payment.upgrade_account') %></button>
45
45
  <% end %>
46
- <%= link_to "Cancel", owner_subscriptions_path(@owner), class: 'btn' %>
46
+ <%= link_to t('koudoku.payment.cancel'), owner_subscriptions_path(@owner), class: 'btn' %>
47
47
  </div>
48
48
  </div>
49
49
 
@@ -7,11 +7,11 @@
7
7
  <h4><%= plan_price(plan) %></h4>
8
8
  <div class="call-to-action">
9
9
  <% if @subscription.nil? %>
10
- <%= link_to Koudoku.free_trial? ? 'Start Trial' : 'Sign Up', koudoku.new_subscription_path(plan: plan.id), class: "btn btn-success btn-large" %>
10
+ <%= link_to Koudoku.free_trial? ? t('koudoku.plan_difference.start_trial') : t('koudoku.subscriptions.sign_up'), koudoku.new_subscription_path(plan: plan.id), class: "btn btn-success btn-large" %>
11
11
  <% elsif @subscription.persisted? %>
12
12
  <% if @subscription.plan == plan %>
13
13
  <%= form_for @subscription, url: owner_subscription_path(@owner, @subscription) do |f| %>
14
- <%= f.submit 'Selected', class: "btn btn-large", disabled: 'disabled' %>
14
+ <%= f.submit t('koudoku.plan_difference.selected'), class: "btn btn-large", disabled: 'disabled' %>
15
15
  <% end %>
16
16
  <% else %>
17
17
  <%= form_for @subscription, url: owner_subscription_path(@owner, @subscription) do |f| %>
@@ -20,12 +20,12 @@
20
20
  <% end %>
21
21
  <% end %>
22
22
  <% else %>
23
- <%= link_to Koudoku.free_trial? ? 'Start Trial' : 'Upgrade', new_owner_subscription_path(@owner, plan: plan.id), class: "btn btn-success btn-large" %>
23
+ <%= link_to Koudoku.free_trial? ? t('koudoku.plan_difference.start_trial') : t('koudoku.plan_difference.upgrade'), new_owner_subscription_path(@owner, plan: plan.id), class: "btn btn-success btn-large" %>
24
24
  <% end %>
25
25
  </div>
26
26
  <ul class="features">
27
27
  <% if Koudoku.free_trial? %>
28
- <li class='muted'><%= Koudoku.free_trial_length %>-day Free Trial</li>
28
+ <li class='muted'><%= t('koudoku.subscriptions.free_trial_for_days', :days => Koudoku.free_trial_length) %></li>
29
29
  <% end %>
30
30
  <%= BlueCloth.new(plan.features.gsub(/\n/, "\n\n")).to_html.gsub(/<(\/?)p>/, '<\1li>').html_safe %>
31
31
  </ul>
@@ -1,11 +1,11 @@
1
1
  <blockquote>
2
- <h4>"Some Great Quote"</h4> &mdash; Person at Place
2
+ <h4><%= t('koudoku.social_proof.testimonial1.quote') %></h4> &mdash; <%= t('koudoku.social_proof.testimonial1.person') %>
3
3
  </blockquote>
4
4
 
5
5
  <blockquote>
6
- <h4>"This is a great service and you've been the best ever! Thanks!"</h4> &mdash; Person at Place
6
+ <h4><%= t('koudoku.social_proof.testimonial2.quote') %></h4> &mdash; <%= t('koudoku.social_proof.testimonial2.person') %>
7
7
  </blockquote>
8
8
 
9
9
  <blockquote>
10
- <h4>"I love you guys and you're the best! You're the best!"</h4> &mdash; Person at Place
10
+ <h4><%= t('koudoku.social_proof.testimonial3.quote') %></h4> &mdash; <%= t('koudoku.social_proof.testimonial3.person') %>
11
11
  </blockquote>
@@ -1,7 +1,7 @@
1
1
  <% if params['update'] == 'card' %>
2
- <%= render 'card', title: "Update Your Payment Information", url: owner_subscription_path(@owner, @subscription) %>
2
+ <%= render 'card', title: t('koudoku.payment.update_payment_information'), url: owner_subscription_path(@owner, @subscription) %>
3
3
  <% else %>
4
- <h1>What Plan Is Best For You?</h1>
4
+ <h1><%= t('koudoku.subscriptions.which_plan_is_best') %></h1>
5
5
  <%= render 'pricing_table' %>
6
- <p>You can also <%= link_to 'cancel your subscription', cancel_owner_subscription_path(@owner, @subscription), method: :post %>.</p>
6
+ <p><%= t('koudoku.subscriptions.cancel_your_subscription_note_html', :link => (link_to t('koudoku.subscriptions.cancel_your_subscription'), cancel_owner_subscription_path(@owner, @subscription), method: :post)) %></p>
7
7
  <% end %>
@@ -1,2 +1,2 @@
1
- <h1>What Plan Is Best For You?</h1>
1
+ <h1><%= t('koudoku.subscriptions.which_plan_is_best') %></h1>
2
2
  <%= render 'pricing_table' %>
@@ -1 +1 @@
1
- <%= render 'card', title: (Koudoku.free_trial? ? "Start Your Free Trial" : "Upgrade Your Account"), url: owner_subscriptions_path(@owner) %>
1
+ <%= render 'card', title: (Koudoku.free_trial? ? t('koudoku.subscriptions.start_trial') : t('koudoku.subscriptions.upgrade_your_account')), url: owner_subscriptions_path(@owner) %>
@@ -1,15 +1,15 @@
1
1
  <% if @subscription.plan.present? %>
2
- <h2>You're Subscribed!</h2>
3
- <p>You're currently subscribed to the <%= @subscription.plan.name %> plan.</p>
4
- <%= link_to 'Choose Another Plan', edit_owner_subscription_path(@owner, @subscription), class: 'btn' %>
2
+ <h2><%= t('koudoku.subscriptions.subscribed') %></h2>
3
+ <p><%= t('koudoku.subscriptions.subscribed_to_plan', :plan => @subscription.plan.name) %></p>
4
+ <%= link_to t('koudoku.subscriptions.choose_other_plan'), edit_owner_subscription_path(@owner, @subscription), class: 'btn' %>
5
5
  <% else %>
6
- <h2>No Subscription</h2>
7
- <p>You are not subscribed to a paid plan.</p>
8
- <%= link_to 'Choose A Plan', edit_owner_subscription_path(@owner, @subscription), class: 'btn' %>
6
+ <h2><%= t('koudoku.subscriptions.no_subscription') %></h2>
7
+ <p><%= t('koudoku.subscriptions.not_subscribed_to_plan') %></p>
8
+ <%= link_to t('koudoku.subscriptions.choose_plan'), edit_owner_subscription_path(@owner, @subscription), class: 'btn' %>
9
9
  <% end %>
10
10
 
11
11
  <br><br>
12
12
 
13
- <h4>Payment Information</h4>
14
- <p>The card on file for your account ends with <%= @subscription.last_four %>.</p>
15
- <%= link_to 'Update Payment Information', edit_owner_subscription_path(@owner, @subscription, update: 'card'), class: 'btn' %>
13
+ <h4><%= t('koudoku.payment.payment_information') %></h4>
14
+ <p><%= t('koudoku.payment.card_on_file_with_last_four', :last_four => @subscription.last_four) %></p>
15
+ <%= link_to t('koudoku.payment.update_payment_information'), edit_owner_subscription_path(@owner, @subscription, update: 'card'), class: 'btn' %>
@@ -1 +1 @@
1
- <h1>Unauthorized</h1>
1
+ <h1><%= t('koudoku.failure.unauthorized') %></h1>
@@ -0,0 +1,58 @@
1
+ # Sample localization file for English. Add more files in this directory for other locales.
2
+ # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3
+
4
+ en:
5
+ koudoku:
6
+ confirmations:
7
+ feature_depends_on_devise: "This feature depends on Devise for authentication."
8
+ subscription_cancelled: "You've successfully cancelled your subscription."
9
+ subscription_updated: "You've successfully updated your subscription."
10
+ subscription_upgraded: "You've been successfully upgraded."
11
+ failure:
12
+ problem_processing_transaction: "There was a problem processing this transaction."
13
+ unauthorized: "Unauthorized"
14
+ plan_intervals:
15
+ month: "month"
16
+ year: "year"
17
+ week: "week"
18
+ 6month: "half-year"
19
+ 3month: "quarter"
20
+ plan_difference:
21
+ downgrade: "Downgrade"
22
+ selected: "Selected"
23
+ start_trial: "Start Trial"
24
+ upgrade: "Upgrade"
25
+ payment:
26
+ cancel: "Cancel"
27
+ card_number: "Card Number"
28
+ card_on_file_with_last_four: "The card on file for your account ends with %{last_four}."
29
+ cvc: "CVC"
30
+ expiration: "Expiration (MM/YYYY)"
31
+ payment_information: "Payment Information"
32
+ save_billing_info: "Save Billing Information"
33
+ upgrade_account: "Upgrade Your Account"
34
+ update_payment_information: "Update Your Payment Information"
35
+ social_proof:
36
+ testimonial1:
37
+ person: "Person at Place"
38
+ quote: "\"Some Great Quote\""
39
+ testimonial2:
40
+ person: "Person at Place"
41
+ quote: "\"This is a great service and you've been the best ever! Thanks!\""
42
+ testimonial3:
43
+ person: "Person at Place"
44
+ quote: "\"I love you guys and you're the best! You're the best!\""
45
+ subscriptions:
46
+ cancel_your_subscription: "cancel your subscription"
47
+ cancel_your_subscription_note_html: "You can also %{link}."
48
+ choose_other_plan: "Choose Another Plan"
49
+ choose_plan: "Choose A Plan"
50
+ free_trial_for_days: "%{days}-day Free Trial"
51
+ no_subscription: "No Subscription"
52
+ not_subscribed_to_plan: "You are not subscribed to a paid plan."
53
+ sign_up: "Sign up"
54
+ start_trial: "Start Your Free Trial"
55
+ subscribed: "You're Subscribed!"
56
+ subscribed_to_plan: "You're currently subscribed to the %{plan} plan."
57
+ upgrade_your_account: "Upgrade Your Account"
58
+ which_plan_is_best: "What Plan Is Best For You?"
@@ -0,0 +1,57 @@
1
+ # Translation by Lauro Becker (http://www.organicadigital.com)
2
+
3
+ pt-BR:
4
+ koudoku:
5
+ confirmations:
6
+ feature_depends_on_devise: "Esta funcionalidade necessita do Devise para autenticação."
7
+ subscription_cancelled: "Você cancelou sua subscrição com sucesso."
8
+ subscription_updated: "Você atualizou sua subscrição com sucesso."
9
+ subscription_upgraded: "Upgrade feito com sucesso."
10
+ failure:
11
+ problem_processing_transaction: "Ocorreu um problema processando a transação."
12
+ unauthorized: "Não autorizado"
13
+ plan_intervals:
14
+ month: "mês"
15
+ year: "ano"
16
+ week: "semana"
17
+ 6month: "6 meses"
18
+ 3month: "3 meses"
19
+ plan_difference:
20
+ downgrade: "Diminuir"
21
+ selected: "Selecionado"
22
+ start_trial: "Iniciar teste"
23
+ upgrade: "Upgrade"
24
+ payment:
25
+ cancel: "Cancelar"
26
+ card_number: "Número do Cartão"
27
+ card_on_file_with_last_four: "O cartão de sua conta termina com %{last_four}."
28
+ cvc: "CVC"
29
+ expiration: "Expiração (MM/YYYY)"
30
+ payment_information: "Informações de Pagamento"
31
+ save_billing_info: "Salvar Informações de Cobrança"
32
+ upgrade_account: "Upgrade de Sua Conta"
33
+ update_payment_information: "Atualizar suas Informações de Pagamento"
34
+ social_proof:
35
+ testimonial1:
36
+ person: "Person at Place"
37
+ quote: "\"Some Great Quote\""
38
+ testimonial2:
39
+ person: "Person at Place"
40
+ quote: "\"This is a great service and you've been the best ever! Thanks!\""
41
+ testimonial3:
42
+ person: "Person at Place"
43
+ quote: "\"I love you guys and you're the best! You're the best!\""
44
+ subscriptions:
45
+ cancel_your_subscription: "cancelar sua subscrição"
46
+ cancel_your_subscription_note_html: "Você também pode %{link}."
47
+ choose_other_plan: "Escolher Outro Plano"
48
+ choose_plan: "Escolha Um Plano"
49
+ free_trial_for_days: "%{days} dias de teste"
50
+ no_subscription: "Nenhuma Subscrição"
51
+ not_subscribed_to_plan: "Você não está subscrito em um plano pago."
52
+ sign_up: "Cadastrar-se"
53
+ start_trial: "Iniciar seu período de testes"
54
+ subscribed: "Você está subscrito!"
55
+ subscribed_to_plan: "Você está atualmente subscrito ao plano %{plan}."
56
+ upgrade_your_account: "Upgrade de Sua Conta"
57
+ which_plan_is_best: "Qual é o melhor plano para você?"
@@ -3,6 +3,6 @@ class Subscription < ActiveRecord::Base
3
3
 
4
4
  <%= "attr_accessible :credit_card_token" if Rails::VERSION::MAJOR == 3 %>
5
5
  belongs_to :<%= subscription_owner_model %>
6
- belongs_to :coupon
6
+ belongs_to :coupon, optional: true
7
7
 
8
8
  end
@@ -2,17 +2,17 @@ Koudoku.setup do |config|
2
2
  config.subscriptions_owned_by = :<%= subscription_owner_model %>
3
3
  config.stripe_publishable_key = ENV['STRIPE_PUBLISHABLE_KEY']
4
4
  config.stripe_secret_key = ENV['STRIPE_SECRET_KEY']
5
-
6
- Stripe.api_version = '2015-01-11' #Making sure the API version used is compatible.
5
+
6
+ Stripe.api_version = '2017-08-15' # Making sure the API version used is compatible.
7
7
  # config.prorate = false # Default is true, set to false to disable prorating subscriptions
8
8
  # config.free_trial_length = 30
9
9
 
10
10
  # Specify layout you want to use for the subscription pages, default is application
11
11
  config.layout = 'application'
12
-
12
+
13
13
  # you can subscribe to additional webhooks here
14
- # we use stripe_event under the hood and you can subscribe using the
15
- # stripe_event syntax on the config object:
14
+ # we use stripe_event under the hood and you can subscribe using the
15
+ # stripe_event syntax on the config object:
16
16
  # config.subscribe 'charge.failed', Koudoku::ChargeFailed
17
-
17
+
18
18
  end
@@ -1,4 +1,5 @@
1
1
  require "koudoku/engine"
2
+ require "koudoku/errors"
2
3
  require "generators/koudoku/install_generator"
3
4
  require "generators/koudoku/views_generator"
4
5
  require 'stripe_event'
@@ -6,51 +7,58 @@ require 'stripe_event'
6
7
  module Koudoku
7
8
  mattr_accessor :subscriptions_owned_by
8
9
  @@subscriptions_owned_by = nil
9
-
10
+
11
+ mattr_accessor :subscriptions_owned_through
12
+ @@subscriptions_owned_through = nil
13
+
14
+ def self.subscriptions_owned_through_or_by
15
+ @@subscriptions_owned_through || @@subscriptions_owned_by
16
+ end
17
+
10
18
  mattr_accessor :stripe_publishable_key
11
19
  @@stripe_publishable_key = nil
12
-
20
+
13
21
  mattr_accessor :stripe_secret_key
14
22
  @@stripe_secret_key = nil
15
-
23
+
16
24
  mattr_accessor :free_trial_length
17
25
  @@free_trial_length = nil
18
26
 
19
27
  mattr_accessor :prorate
20
28
  @@prorate = true
21
29
 
22
-
30
+
23
31
  @@layout = nil
24
-
32
+
25
33
  def self.layout
26
34
  @@layout || 'application'
27
35
  end
28
-
36
+
29
37
  def self.layout=(layout)
30
38
  @@layout = layout
31
39
  end
32
-
40
+
33
41
  def self.webhooks_api_key=(key)
34
42
  raise "Koudoku no longer uses an API key to secure webhooks, please delete the line from \"config/initializers/koudoku.rb\""
35
43
  end
36
-
44
+
37
45
  def self.setup
38
46
  yield self
39
-
47
+
40
48
  # Configure the Stripe gem.
41
49
  Stripe.api_key = stripe_secret_key
42
50
  end
43
-
51
+
44
52
  # e.g. :users
45
53
  def self.owner_resource
46
54
  subscriptions_owned_by.to_s.pluralize.to_sym
47
55
  end
48
-
56
+
49
57
  # e.g. :user_id
50
58
  def self.owner_id_sym
51
59
  :"#{Koudoku.subscriptions_owned_by}_id"
52
60
  end
53
-
61
+
54
62
  # e.g. :user=
55
63
  def self.owner_assignment_sym
56
64
  :"#{Koudoku.subscriptions_owned_by}="
@@ -60,12 +68,12 @@ module Koudoku
60
68
  def self.owner_class
61
69
  Koudoku.subscriptions_owned_by.to_s.classify.constantize
62
70
  end
63
-
71
+
64
72
  def self.free_trial?
65
73
  free_trial_length.to_i > 0
66
74
  end
67
-
68
-
75
+
76
+
69
77
  #
70
78
  # STRIPE_EVENT section
71
79
  #
@@ -0,0 +1,4 @@
1
+ module Koudoku
2
+ class Error < StandardError; end
3
+ class NilCardToken < Error; end
4
+ end
@@ -1,3 +1,3 @@
1
1
  module Koudoku
2
- VERSION = "1.2.4"
2
+ VERSION = "2.0.0"
3
3
  end
File without changes
@@ -1,4 +1,4 @@
1
- class CreateCustomers < ActiveRecord::Migration
1
+ class CreateCustomers < ActiveRecord::Migration[5.1]
2
2
  def change
3
3
  create_table :customers do |t|
4
4
  t.string :email
@@ -1,4 +1,4 @@
1
- class CreateSubscriptions < ActiveRecord::Migration
1
+ class CreateSubscriptions < ActiveRecord::Migration[5.1]
2
2
  def change
3
3
  create_table :subscriptions do |t|
4
4
  t.string :stripe_id
@@ -1,4 +1,4 @@
1
- class CreatePlans < ActiveRecord::Migration
1
+ class CreatePlans < ActiveRecord::Migration[5.1]
2
2
  def change
3
3
  create_table :plans do |t|
4
4
  t.string :name
@@ -1,4 +1,4 @@
1
- class CreateCoupons < ActiveRecord::Migration
1
+ class CreateCoupons < ActiveRecord::Migration[5.1]
2
2
  def change
3
3
  create_table :coupons do |t|
4
4
  t.string :code
@@ -1,4 +1,4 @@
1
- class AddIntervalToPlan < ActiveRecord::Migration
1
+ class AddIntervalToPlan < ActiveRecord::Migration[5.1]
2
2
  def change
3
3
  add_column :plans, :interval, :string
4
4
  end
@@ -1,4 +1,3 @@
1
- # encoding: UTF-8
2
1
  # This file is auto-generated from the current state of the database. Instead
3
2
  # of editing this file, please use the migrations feature of Active Record to
4
3
  # incrementally modify your database, and then regenerate this schema definition.
@@ -9,45 +8,45 @@
9
8
  # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
9
  # you'll amass, the slower it'll run and the greater likelihood for issues).
11
10
  #
12
- # It's strongly recommended to check this file into your version control system.
11
+ # It's strongly recommended that you check this file into your version control system.
13
12
 
14
- ActiveRecord::Schema.define(:version => 20130520163946) do
13
+ ActiveRecord::Schema.define(version: 20130520163946) do
15
14
 
16
- create_table "coupons", :force => true do |t|
17
- t.string "code"
18
- t.string "free_trial_length"
19
- t.datetime "created_at", :null => false
20
- t.datetime "updated_at", :null => false
15
+ create_table "coupons", force: :cascade do |t|
16
+ t.string "code"
17
+ t.string "free_trial_length"
18
+ t.datetime "created_at", null: false
19
+ t.datetime "updated_at", null: false
21
20
  end
22
21
 
23
- create_table "customers", :force => true do |t|
24
- t.string "email"
25
- t.datetime "created_at", :null => false
26
- t.datetime "updated_at", :null => false
22
+ create_table "customers", force: :cascade do |t|
23
+ t.string "email"
24
+ t.datetime "created_at", null: false
25
+ t.datetime "updated_at", null: false
27
26
  end
28
27
 
29
- create_table "plans", :force => true do |t|
30
- t.string "name"
31
- t.string "stripe_id"
32
- t.float "price"
33
- t.text "features"
34
- t.boolean "highlight"
35
- t.integer "display_order"
36
- t.datetime "created_at", :null => false
37
- t.datetime "updated_at", :null => false
38
- t.string "interval"
28
+ create_table "plans", force: :cascade do |t|
29
+ t.string "name"
30
+ t.string "stripe_id"
31
+ t.float "price"
32
+ t.text "features"
33
+ t.boolean "highlight"
34
+ t.integer "display_order"
35
+ t.datetime "created_at", null: false
36
+ t.datetime "updated_at", null: false
37
+ t.string "interval"
39
38
  end
40
39
 
41
- create_table "subscriptions", :force => true do |t|
42
- t.string "stripe_id"
43
- t.integer "plan_id"
44
- t.string "last_four"
45
- t.integer "coupon_id"
46
- t.string "card_type"
47
- t.float "current_price"
48
- t.integer "customer_id"
49
- t.datetime "created_at", :null => false
50
- t.datetime "updated_at", :null => false
40
+ create_table "subscriptions", force: :cascade do |t|
41
+ t.string "stripe_id"
42
+ t.integer "plan_id"
43
+ t.string "last_four"
44
+ t.integer "coupon_id"
45
+ t.string "card_type"
46
+ t.float "current_price"
47
+ t.integer "customer_id"
48
+ t.datetime "created_at", null: false
49
+ t.datetime "updated_at", null: false
51
50
  end
52
51
 
53
52
  end
File without changes
File without changes
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: koudoku
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Culver
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-10 00:00:00.000000000 Z
11
+ date: 2017-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -181,6 +181,8 @@ files:
181
181
  - app/views/layouts/koudoku/application.html.erb
182
182
  - config/environment.rb
183
183
  - config/initializers/stripe_event.rb
184
+ - config/locales/en.yml
185
+ - config/locales/pt-BR.yml
184
186
  - config/routes.rb
185
187
  - lib/generators/koudoku/install_generator.rb
186
188
  - lib/generators/koudoku/templates/app/models/coupon.rb
@@ -190,6 +192,7 @@ files:
190
192
  - lib/generators/koudoku/views_generator.rb
191
193
  - lib/koudoku.rb
192
194
  - lib/koudoku/engine.rb
195
+ - lib/koudoku/errors.rb
193
196
  - lib/koudoku/version.rb
194
197
  - lib/tasks/koudoku_tasks.rake
195
198
  - spec/concerns/koudoku/plan_spec.rb
@@ -271,7 +274,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
271
274
  version: '0'
272
275
  requirements: []
273
276
  rubyforge_project:
274
- rubygems_version: 2.2.2
277
+ rubygems_version: 2.6.8
275
278
  signing_key:
276
279
  specification_version: 4
277
280
  summary: Robust subscription support for Rails with Stripe.