effective_orders 4.1.5 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1cbc4c38cb22371fa03bfa9319d76cbf3e45ac1a3c75edfedb6486d36bd91d7b
4
- data.tar.gz: ec41a7da268206d32b25cb8cbf4cf6cd3de2c552159cc9f823e730c02a6e06b0
3
+ metadata.gz: cba395b26b2db05cfcbfd3340db1c83318f97a190130b7f009363314a45b2a51
4
+ data.tar.gz: 5e9e3a2de5aee44d4fbde7374dee306ad9acffa30513f97e073050d04acb2955
5
5
  SHA512:
6
- metadata.gz: 6f983b6121c2842fbe5ac6a05d105d088d085f05ee42e2fbafd92e8dc99850e511b2696d8a962df8a73604dbb2a830c7343c606f94859471c3fce88aa3ed70ed
7
- data.tar.gz: e155ef077626ed3f479f7a11fbc6c1f83475e01352e54d8b0e3aef781675e07013799092c8ae3a16f63a8863dbbc3a95d84d10750d3c8386b23d6fac151ef204
6
+ metadata.gz: 0c4bbcc96e0ba2ace04bb7779b4c56aaa2578fb3b7c05ecfb2979b94c4fd8a12581fc3d9a77de1f267cf3ff1e00104f122b49dc29354ea7b95e5c91c2b2c5f1e
7
+ data.tar.gz: b48693aa3680d77555a459366c7379ba96b6b2894c40dbe01bd1a630440843a414d393a2cc84946130c1a59ae5290d5576f15d0cd16145ad2df31ee22e01f7a7
@@ -20,7 +20,9 @@ $(document).on 'change keyup', '.effective-orders-subscripter-plan-quantity', (e
20
20
  return unless $plan.length == 1
21
21
 
22
22
  # Assign the quantity to each quantity field
23
- $plan.closest('form').find(".effective-orders-stripe-plan:not([data-plan-id='#{$plan.data('id')}'])").find("input[name$='[quantity]']").val($obj.val())
23
+ $plan.closest('form')
24
+ .find(".effective-orders-stripe-plan:not([data-plan-id='#{$plan.data('id')}'])")
25
+ .find("input[name$='[quantity]']").val($obj.val())
24
26
 
25
27
  quantity = $obj.val() || 0
26
28
 
@@ -28,11 +30,9 @@ $(document).on 'change keyup', '.effective-orders-subscripter-plan-quantity', (e
28
30
  # Assign all totals
29
31
  plan = $(this)
30
32
  amount = parseInt(plan.data('amount'))
31
- interval = plan.data('plan-interval')
33
+ interval = plan.data('interval')
32
34
 
33
35
  total = (quantity * amount)
34
- total = (total / 12) if interval == 'year'
35
-
36
36
  total = '$' + (total / 100.0).toFixed(2)
37
37
 
38
38
  plan.find('#effective_subscripter_total_amount').text(total)
@@ -53,6 +53,9 @@ $(document).on 'click', ".effective-orders-stripe-token-required[type='submit'],
53
53
  stripe = $form.data('stripe')
54
54
  return unless stripe?
55
55
 
56
+ plans = $form.data('plans')
57
+ return unless plans?
58
+
56
59
  # If we're doing choose button mode
57
60
  if $obj.data('choose-stripe-plan-id')
58
61
  $form.find("input[name$='[stripe_plan_id]']").val($obj.data('choose-stripe-plan-id'))
@@ -63,7 +66,7 @@ $(document).on 'click', ".effective-orders-stripe-token-required[type='submit'],
63
66
  return unless selected_plan_id.length > 0
64
67
 
65
68
  # Match plan
66
- plan = stripe.plans.find (plan, _) => plan.id == selected_plan_id
69
+ plan = plans.find (plan, _) => plan.id == selected_plan_id
67
70
  return unless plan?
68
71
 
69
72
  # Okay, we're good to call stripe
@@ -4,7 +4,7 @@ module EffectiveStripeHelper
4
4
  plan = (
5
5
  case obj
6
6
  when Hash ; obj
7
- when ::Stripe::Plan ; EffectiveOrders.stripe_plans.find { |plan| plan.id == obj.id }
7
+ when ::Stripe::Plan ; EffectiveOrders.stripe_plans.find { |plan| plan[:id] == obj.id }
8
8
  else ; raise 'unexpected object'
9
9
  end
10
10
  )
@@ -1,10 +1,16 @@
1
1
  module EffectiveSubscriptionsHelper
2
2
 
3
- def stripe_plans_collection(subscripter = nil)
4
- EffectiveOrders.stripe_plans.values.sort do |x, y|
5
- amount = (x[:amount] <=> y[:amount])
6
- (amount != 0) ? amount : x[:name] <=> y[:name]
7
- end
3
+ def subscripter_stripe_data(subscripter)
4
+ {
5
+ email: current_user.email,
6
+ image: stripe_site_image_url,
7
+ key: EffectiveOrders.stripe[:publishable_key],
8
+ name: EffectiveOrders.stripe[:site_title],
9
+ }
10
+ end
11
+
12
+ def subscripter_stripe_plans(subscripter)
13
+ EffectiveOrders.stripe_plans
8
14
  end
9
15
 
10
16
  def subscribable_form_with(subscribable)
@@ -25,14 +31,6 @@ module EffectiveSubscriptionsHelper
25
31
  render('effective/customers/form', subscripter: subscripter)
26
32
  end
27
33
 
28
- def subscripter_stripe_data(subscripter)
29
- {
30
- email: current_user.email,
31
- image: stripe_site_image_url,
32
- key: EffectiveOrders.stripe[:publishable_key],
33
- name: EffectiveOrders.stripe[:site_title],
34
- plans: EffectiveOrders.stripe_plans.values
35
- }
36
- end
34
+
37
35
 
38
36
  end
@@ -11,7 +11,11 @@ module Effective
11
11
  validates :subscribable, presence: true, if: -> { stripe_plan_id.present? }
12
12
  validates :customer, presence: true
13
13
 
14
- validates :stripe_plan_id, inclusion: { allow_blank: true, in: EffectiveOrders.stripe_plans.keys, message: 'unknown plan' }
14
+ validates :stripe_plan_id, inclusion: {
15
+ allow_blank: true,
16
+ in: EffectiveOrders.stripe_plans.map { |plan| plan[:id] },
17
+ message: 'unknown plan'
18
+ }
15
19
 
16
20
  validate(if: -> { stripe_plan_id && plan && plan[:amount] > 0 }) do
17
21
  self.errors.add(:stripe_token, 'updated payment card required') if stripe_token.blank? && token_required?
@@ -43,7 +47,7 @@ module Effective
43
47
  end
44
48
 
45
49
  def plan
46
- EffectiveOrders.stripe_plans[stripe_plan_id]
50
+ EffectiveOrders.stripe_plans.find { |plan| plan[:id] == stripe_plan_id }
47
51
  end
48
52
 
49
53
  def quantity=(value)
@@ -45,7 +45,9 @@ module Effective
45
45
  validates :customer, presence: true
46
46
  validates :subscribable, presence: true
47
47
 
48
- validates :stripe_plan_id, presence: true, inclusion: { in: EffectiveOrders.stripe_plans.keys }
48
+ validates :stripe_plan_id, presence: true
49
+ validates :stripe_plan_id, inclusion: { in: EffectiveOrders.stripe_plans.map { |plan| plan[:id] } }
50
+
49
51
  validates :stripe_subscription_id, presence: true
50
52
 
51
53
  validates :name, presence: true
@@ -59,7 +61,7 @@ module Effective
59
61
  end
60
62
 
61
63
  def plan
62
- EffectiveOrders.stripe_plans[stripe_plan_id]
64
+ EffectiveOrders.stripe_plans.find { |plan| plan[:id] == stripe_plan_id }
63
65
  end
64
66
 
65
67
  def stripe_subscription
@@ -6,14 +6,12 @@
6
6
  %thead
7
7
  %tr
8
8
  %th Subscribed
9
- %th Plan
10
9
  %th Quantity
11
10
  %th Interval
12
11
  %tbody
13
12
  - customer.subscriptions.each do |sub|
14
13
  %tr
15
14
  %td= sub.subscribable
16
- %td= sub
17
15
  %td= sub.quantity
18
16
  %td= sub.interval
19
17
 
@@ -1,23 +1,23 @@
1
1
  = javascript_include_tag 'https://checkout.stripe.com/checkout.js'
2
2
 
3
- = effective_form_with(model: subscripter, url: effective_orders.subscripter_path, remote: true, data: { stripe: subscripter_stripe_data(subscripter) }) do |f|
3
+ - stripe = subscripter_stripe_data(subscripter)
4
+ - plans = subscripter_stripe_plans(subscripter)
5
+
6
+ - subscripter.quantity ||= subscripter.subscribable.subscribable_quantity_used
7
+ - subscripter.stripe_plan_id ||= Hash(plans.first)[:id]
8
+
9
+ = effective_form_with(model: subscripter, url: effective_orders.subscripter_path, remote: true, data: { stripe: stripe, plans: plans }) do |f|
4
10
  = f.hidden_field :subscribable_global_id
5
11
  = f.hidden_field :stripe_token, value: nil
6
- = f.error :stripe_token
7
-
8
12
  = f.hidden_field :stripe_plan_id
9
-
10
- - stripe_plans = stripe_plans_collection(f.object)
11
- - stripe_plans = stripe_plans.select { |plan| plan[:name].include?('per User') }
12
-
13
- - f.object.stripe_plan_id ||= (stripe_plans.first || {})[:id]
13
+ = f.error :stripe_token
14
14
 
15
15
  - if f.object.subscribable.subscribed?
16
16
  - quantity_used = f.object.subscribable.subscribable_quantity_used.to_i
17
17
  - quantity_purchased = f.object.subscribable.subscription.quantity
18
18
 
19
19
  .text-center
20
- %p
20
+ %p
21
21
  You currently have <strong>#{pluralize(quantity_used, 'member')}</strong> in your team
22
22
  and have space for <strong>#{pluralize(quantity_purchased, 'member')}</strong>.
23
23
 
@@ -26,39 +26,28 @@
26
26
  - else
27
27
  %p To add more members you will need to update your plan.
28
28
 
29
- %p To pay for less than #{pluralize(quantity_used, 'member')} you'll have to remove some first.
29
+ %p To pay for less than #{pluralize(quantity_used, 'member')}, remove some team members first.
30
30
 
31
- .card.mb-4
32
- .card-body.text-center
33
- %h5.card-title Billing Cycle
31
+ - else
32
+ .text-center
33
+ %p
34
+ You are not currently subscribed to any plan.
35
+ %br
36
+ For full access, upgrade to a paid plan below.
37
+ %br
38
+ To upgrade with fewer people, remove some team members first.
34
39
 
35
- = f.radios :stripe_plan_id, stripe_plans.map { |plan| [plan[:name], plan[:id]] }, label: false, buttons: true
40
+ .card.mb-4
41
+ .card-body.card-subscripter
42
+ %h5.card-title.subscripter-title Billing Cycle
36
43
 
37
- %hr
44
+ = f.radios :stripe_plan_id, plans.map { |plan| [plan[:name], plan[:id]] }, label: false, buttons: true
38
45
 
39
- - stripe_plans.select { |plan| plan[:interval] == 'month' }.each do |plan|
40
- = f.show_if(:stripe_plan_id, plan[:id]) do
41
- .effective-orders-stripe-plan{'data-id': plan[:id], 'data-amount': plan[:amount], 'data-interval': plan[:interval]}
42
- .d-flex.justify-content-around.align-items-center
43
- = f.number_field :quantity, class: 'effective-orders-subscripter-plan-quantity form-control-lg', autocomplete: 'off', required: true
44
- %div= 'x'
45
- = f.static_field :price_per_person do
46
- = price_to_currency(plan[:amount])
47
- %div= '='
48
- = f.static_field :total_amount do
49
- = price_to_currency(plan[:amount] * f.object.quantity.to_i)
46
+ %hr.mt-4.mb-4
50
47
 
51
- - stripe_plans.select { |plan| plan[:interval] == 'year' }.each do |plan|
48
+ - plans.each do |plan|
52
49
  = f.show_if(:stripe_plan_id, plan[:id]) do
53
- .effective-orders-stripe-plan{'data-id': plan[:id], 'data-amount': plan[:amount], 'data-interval': plan[:interval]}
54
- .d-flex.justify-content-around.align-items-center
55
- = f.number_field :quantity, class: 'effective-orders-subscripter-plan-quantity form-control-lg', autocomplete: 'off', required: true
56
- %div= 'x'
57
- = f.static_field :price_per_person do
58
- = price_to_currency(plan[:amount] / 12)
59
- %div= '='
60
- = f.static_field :total_amount do
61
- = price_to_currency(plan[:amount] * f.object.quantity.to_i)
50
+ = render 'effective/subscripter/plan', plan: plan, f: f
62
51
 
63
52
  = f.submit(border: false, center: true) do
64
- = f.save('Update Plan', class: ('effective-orders-stripe-token-required' if f.object.token_required?))
53
+ = f.save('Continue to Billing', class: ('effective-orders-stripe-token-required' if f.object.token_required?))
@@ -0,0 +1,23 @@
1
+ .effective-orders-stripe-plan{data: plan}
2
+ .d-flex.justify-content-around.align-top
3
+ = f.integer_field :quantity, autocomplete: 'off', required: true, label: 'Total People', maxlength: 3,
4
+ class: 'effective-orders-subscripter-plan-quantity form-control-lg'
5
+
6
+ .subscripter-math-symbol= 'x'
7
+
8
+ = f.static_field :price_per_person, label: 'Price Per Person' do
9
+ = price_to_currency(plan[:amount])
10
+
11
+ - if plan[:savings]
12
+ .subscripter-savings.text-danger
13
+ Save #{price_to_currency(plan[:savings])}/person
14
+
15
+ .subscripter-math-symbol= '='
16
+
17
+ = f.static_field :total_amount, label: 'Total Amount' do
18
+ = price_to_currency(plan[:amount] * f.object.quantity.to_i)
19
+
20
+ - if plan[:savings]
21
+ .subscripter-total-savings.text-danger
22
+ Save
23
+ %span #{price_to_currency(f.object.quantity.to_i * plan[:savings])}
@@ -166,7 +166,7 @@ module EffectiveOrders
166
166
  end
167
167
 
168
168
  def self.stripe_plans
169
- return {} unless (stripe? && subscriptions?)
169
+ return [] unless (stripe? && subscriptions?)
170
170
 
171
171
  @stripe_plans ||= (
172
172
  Rails.logger.info '[STRIPE] index plans'
@@ -177,24 +177,53 @@ module EffectiveOrders
177
177
  raise e if Rails.env.production?
178
178
  Rails.logger.info "[STRIPE ERROR]: #{e.message}"
179
179
  Rails.logger.info "[STRIPE ERROR]: effective_orders continuing with empty stripe plans. This would fail loudly in Rails.env.production."
180
- {}
180
+ []
181
181
  end
182
182
 
183
- plans.inject({}) do |h, plan|
184
- h[plan.id] = {
183
+ plans = plans.map do |plan|
184
+ {
185
185
  id: plan.id,
186
186
  product_id: plan.product,
187
187
  name: plan.nickname,
188
188
  amount: plan.amount,
189
189
  currency: plan.currency,
190
- description: "$#{'%0.2f' % (plan.amount / 100.0)} #{plan.currency.upcase}/#{plan.interval}",
190
+ description: ("$#{'%0.2f' % (plan.amount / 100.0)}" + ' ' + plan.currency.upcase + '/' + plan.interval.to_s),
191
191
  interval: plan.interval,
192
192
  interval_count: plan.interval_count
193
- }; h
193
+ }
194
+ end.sort do |x, y|
195
+ val ||= (x[:interval] <=> y[:interval])
196
+ val = nil if val == 0
197
+
198
+ val ||= (x[:amount] <=> y[:amount])
199
+ val = nil if val == 0
200
+
201
+ val ||= (x[:name] <=> y[:name])
202
+ val = nil if val == 0
203
+
204
+ val || (x[:id] <=> y[:id])
205
+ end
206
+
207
+ # Calculate savings for any yearly per user plans, based on their matching monthly plans
208
+ plans.select { |plan| plan[:interval] == 'year' && plan[:name].downcase.include?('per') }.each do |yearly|
209
+ monthly_name = yearly[:name].downcase.gsub('year', 'month')
210
+ monthly = plans.find { |plan| plan[:interval] == 'month' && plan[:name].downcase == monthly_name }
211
+ next unless monthly
212
+
213
+ savings = (monthly[:amount].to_i * 12) - yearly[:amount].to_i
214
+ next unless savings > 0
215
+
216
+ yearly[:savings] = savings
194
217
  end
218
+
219
+ plans
195
220
  )
196
221
  end
197
222
 
223
+ def self.stripe_plans_collection
224
+ stripe_plans.map { |plan| [plan[:name], plan[:id]] }
225
+ end
226
+
198
227
  class SoldOutException < Exception; end
199
228
  class AlreadyPurchasedException < Exception; end
200
229
  end
@@ -1,3 +1,3 @@
1
1
  module EffectiveOrders
2
- VERSION = '4.1.5'.freeze
2
+ VERSION = '4.2.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_orders
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.5
4
+ version: 4.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-15 00:00:00.000000000 Z
11
+ date: 2019-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -231,6 +231,7 @@ files:
231
231
  - app/views/effective/orders_mailer/subscription_trialing.html.haml
232
232
  - app/views/effective/orders_mailer/subscription_updated.html.haml
233
233
  - app/views/effective/subscripter/_form.html.haml
234
+ - app/views/effective/subscripter/_plan.html.haml
234
235
  - app/views/layouts/effective_orders_mailer_layout.html.haml
235
236
  - config/effective_orders.rb
236
237
  - config/routes.rb