effective_orders 4.4.5 → 4.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/javascripts/effective_orders/providers/stripe.js.coffee +77 -0
- data/app/models/concerns/acts_as_purchasable.rb +9 -9
- data/app/models/concerns/acts_as_subscribable.rb +11 -6
- data/app/models/concerns/acts_as_subscribable_buyer.rb +1 -1
- data/app/models/effective/customer.rb +7 -0
- data/app/models/effective/order.rb +3 -2
- data/app/models/effective/subscription.rb +4 -0
- data/app/views/effective/customers/_customer.html.haml +2 -2
- data/lib/effective_orders.rb +7 -4
- data/lib/effective_orders/engine.rb +3 -3
- data/lib/effective_orders/version.rb +1 -1
- metadata +7 -7
- data/app/assets/javascripts/effective_orders/providers/stripe.js +0 -97
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c92ae430fbce8f9ee7692d921653fffda8419a6d76eb2a4b43f3efcc932b7902
|
4
|
+
data.tar.gz: 9ce838e457cb9a3d365641b1d6d975f55fa118eed1df7be6d8071044a845fc38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f2999ad4d947a2f3623d4dfa82aa6f9a31daabef750715bc2d4671dae7f64e3dee7076e26dd6e678b4e1ecc394ea96f4a37f241fc258eea53f533e7040a1216
|
7
|
+
data.tar.gz: 825f4065b65081552b68d6228c5c7d72e96d60cc6967e1789485df31366aa9f6ce5e09c2508604e697180ef7ccd7b9c5e5b75bc94ee9c954cb7dce091c885a5d
|
@@ -0,0 +1,77 @@
|
|
1
|
+
this.StripeForm ||= class StripeForm
|
2
|
+
constructor: ->
|
3
|
+
@form = null
|
4
|
+
@paymentIntent = null
|
5
|
+
|
6
|
+
@data = null
|
7
|
+
@stripe = null
|
8
|
+
@card = null
|
9
|
+
|
10
|
+
initialize: ->
|
11
|
+
@form = $('form[data-stripe-form]').first()
|
12
|
+
return false unless @form.length > 0
|
13
|
+
|
14
|
+
@paymentIntent = @form.find("input[name$='[payment_intent_id]']").first()
|
15
|
+
@data = @form.data('stripe-form')
|
16
|
+
@stripe = Stripe(@data.key)
|
17
|
+
@card = @stripe.elements().create('card', @style())
|
18
|
+
|
19
|
+
@mount()
|
20
|
+
|
21
|
+
style: ->
|
22
|
+
style: {
|
23
|
+
base: { color: '#32325d', fontSize: '16px', },
|
24
|
+
invalid: { color: '#dc3545', iconColor: '#dc3545' }
|
25
|
+
}
|
26
|
+
|
27
|
+
mount: ->
|
28
|
+
@card.mount('#stripe-card-element')
|
29
|
+
|
30
|
+
@card.addEventListener('change', (error) ->
|
31
|
+
$('#stripe-card-errors').text(if error.message then error.message else '')
|
32
|
+
)
|
33
|
+
|
34
|
+
@form.on('click', '[type=submit]', (event) => @submit(event))
|
35
|
+
|
36
|
+
submit: (event) ->
|
37
|
+
event.preventDefault()
|
38
|
+
|
39
|
+
payment = if @shouldUseNewCard() then @useNewCard() else @useExistingCard()
|
40
|
+
|
41
|
+
$.active = $.active + 1
|
42
|
+
|
43
|
+
payment.then((result) =>
|
44
|
+
if result.error
|
45
|
+
@errorPayment(result.error)
|
46
|
+
else if result.paymentIntent.status == 'succeeded'
|
47
|
+
@submitPayment(result.paymentIntent)
|
48
|
+
).then((result) =>
|
49
|
+
$.active = $.active - 1
|
50
|
+
)
|
51
|
+
|
52
|
+
shouldUseNewCard: ->
|
53
|
+
@form.get(0).checkValidity() &&
|
54
|
+
@paymentIntent.val().length == 0 &&
|
55
|
+
(@data.token_required || @form.children('.collapse.show').length > 0)
|
56
|
+
|
57
|
+
useNewCard: ->
|
58
|
+
@stripe.confirmCardPayment(@data.client_secret, {
|
59
|
+
payment_method: {
|
60
|
+
card: @card,
|
61
|
+
billing_details: { email: @data.email }
|
62
|
+
},
|
63
|
+
setup_future_usage: 'off_session'
|
64
|
+
})
|
65
|
+
|
66
|
+
useExistingCard: ->
|
67
|
+
@stripe.confirmCardPayment(@data.client_secret, { payment_method: @data.payment_method })
|
68
|
+
|
69
|
+
submitPayment: (payment) ->
|
70
|
+
@paymentIntent.val(payment['id'])
|
71
|
+
@form.submit()
|
72
|
+
|
73
|
+
errorPayment: (error) ->
|
74
|
+
$('#stripe-card-errors').text(error.message)
|
75
|
+
EffectiveForm.invalidate(@form);
|
76
|
+
|
77
|
+
$ -> (new StripeForm()).initialize()
|
@@ -1,19 +1,19 @@
|
|
1
1
|
module ActsAsPurchasable
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
|
-
module
|
4
|
+
module Base
|
5
5
|
def acts_as_purchasable(*options)
|
6
6
|
@acts_as_purchasable = options || []
|
7
7
|
|
8
|
-
if table_exists?
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
# if table_exists?
|
9
|
+
# instance = new()
|
10
|
+
# raise 'must respond_to price' unless instance.respond_to?(:price)
|
11
|
+
# raise 'must respond_to purchased_order_id' unless instance.respond_to?(:purchased_order_id)
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
13
|
+
# if defined?(EffectiveQbSync)
|
14
|
+
# raise 'must respond to qb_item_name' unless instance.respond_to?(:qb_item_name)
|
15
|
+
# end
|
16
|
+
# end
|
17
17
|
|
18
18
|
include ::ActsAsPurchasable
|
19
19
|
end
|
@@ -3,13 +3,15 @@ module ActsAsSubscribable
|
|
3
3
|
|
4
4
|
mattr_accessor :descendants
|
5
5
|
|
6
|
-
module
|
6
|
+
module Base
|
7
7
|
def acts_as_subscribable(*options)
|
8
8
|
@acts_as_subscribable = options || []
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
raise 'must respond to
|
10
|
+
# if table_exists?
|
11
|
+
# instance = new()
|
12
|
+
# raise 'must respond to trialing_until' unless instance.respond_to?(:trialing_until) || !EffectiveOrders.trial?
|
13
|
+
# raise 'must respond to subscription_status' unless instance.respond_to?(:subscription_status)
|
14
|
+
# end
|
13
15
|
|
14
16
|
include ::ActsAsSubscribable
|
15
17
|
(ActsAsSubscribable.descendants ||= []) << self
|
@@ -20,7 +22,7 @@ module ActsAsSubscribable
|
|
20
22
|
has_one :subscription, as: :subscribable, class_name: 'Effective::Subscription', inverse_of: :subscribable
|
21
23
|
has_one :customer, through: :subscription, class_name: 'Effective::Customer'
|
22
24
|
|
23
|
-
before_validation(if: -> {
|
25
|
+
before_validation(if: -> { EffectiveOrders.trial? && trialing_until.blank? }) do
|
24
26
|
self.trialing_until = (Time.zone.now + EffectiveOrders.trial.fetch(:length)).beginning_of_day
|
25
27
|
end
|
26
28
|
|
@@ -28,7 +30,10 @@ module ActsAsSubscribable
|
|
28
30
|
raise :abort unless (subscripter.destroy! rescue false)
|
29
31
|
end
|
30
32
|
|
31
|
-
|
33
|
+
if EffectiveOrders.trial?
|
34
|
+
validates :trialing_until, presence: true
|
35
|
+
end
|
36
|
+
|
32
37
|
validates :subscription_status, inclusion: { allow_nil: true, in: EffectiveOrders::STATUSES.keys }
|
33
38
|
|
34
39
|
scope :trialing, -> { where(subscription_status: nil).where('trialing_until > ?', Time.zone.now) }
|
@@ -51,6 +51,13 @@ module Effective
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
+
def invoices
|
55
|
+
@invoices ||= if stripe_customer_id.present?
|
56
|
+
Rails.logger.info "[STRIPE] list invoices: #{stripe_customer_id}"
|
57
|
+
::Stripe::Invoice.list(customer: stripe_customer_id) rescue nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
54
61
|
def upcoming_invoice
|
55
62
|
@upcoming_invoice ||= if stripe_customer_id.present?
|
56
63
|
Rails.logger.info "[STRIPE] get upcoming invoice: #{stripe_customer_id}"
|
@@ -337,13 +337,14 @@ module Effective
|
|
337
337
|
|
338
338
|
assign_attributes(
|
339
339
|
state: EffectiveOrders::PURCHASED,
|
340
|
-
purchased_at: Time.zone.now,
|
341
340
|
payment: payment_to_h(payment),
|
342
341
|
payment_provider: provider,
|
343
342
|
payment_card: (card.presence || 'none'),
|
344
343
|
skip_buyer_validations: skip_buyer_validations
|
345
344
|
)
|
346
345
|
|
346
|
+
self.purchased_at ||= Time.zone.now
|
347
|
+
|
347
348
|
Effective::Order.transaction do
|
348
349
|
begin
|
349
350
|
run_purchasable_callbacks(:before_purchase)
|
@@ -504,7 +505,7 @@ module Effective
|
|
504
505
|
end
|
505
506
|
|
506
507
|
def update_purchasables_purchased_order!
|
507
|
-
order_items.each { |oi| oi.purchasable
|
508
|
+
order_items.each { |oi| oi.purchasable&.update_column(:purchased_order_id, self.id) }
|
508
509
|
end
|
509
510
|
|
510
511
|
def run_purchasable_callbacks(name)
|
@@ -56,6 +56,10 @@ module Effective
|
|
56
56
|
|
57
57
|
validates :status, inclusion: { in: EffectiveOrders::STATUSES.keys }
|
58
58
|
|
59
|
+
before_validation do
|
60
|
+
self.name ||= EffectiveOrders.stripe_plans.find { |plan| plan[:id] == stripe_plan_id }&[:name] || 'Subscribed Plan'
|
61
|
+
end
|
62
|
+
|
59
63
|
def to_s
|
60
64
|
name || 'New Subscription'
|
61
65
|
end
|
@@ -15,7 +15,7 @@
|
|
15
15
|
%td= sub.quantity
|
16
16
|
%td= sub.interval
|
17
17
|
|
18
|
-
- if customer.
|
18
|
+
- if customer.invoices.present?
|
19
19
|
.card.my-4
|
20
20
|
.card-header Invoices
|
21
21
|
.card-body
|
@@ -26,7 +26,7 @@
|
|
26
26
|
%th Invoice
|
27
27
|
%th Total
|
28
28
|
%tbody
|
29
|
-
- customer.
|
29
|
+
- customer.invoices.each do |invoice|
|
30
30
|
- date_method = [(:date if invoice.respond_to?(:date)), (:period_start if invoice.respond_to?(:period_start)), :created].compact.first
|
31
31
|
%tr
|
32
32
|
%td= link_to Time.zone.at(invoice.public_send(date_method)).strftime('%F'), invoice.invoice_pdf
|
data/lib/effective_orders.rb
CHANGED
@@ -183,7 +183,7 @@ module EffectiveOrders
|
|
183
183
|
Rails.logger.info '[STRIPE] index plans'
|
184
184
|
|
185
185
|
plans = begin
|
186
|
-
Stripe::Plan.all
|
186
|
+
Stripe::Plan.respond_to?(:all) ? Stripe::Plan.all : Stripe::Plan.list
|
187
187
|
rescue => e
|
188
188
|
raise e if Rails.env.production?
|
189
189
|
Rails.logger.info "[STRIPE ERROR]: #{e.message}"
|
@@ -192,15 +192,18 @@ module EffectiveOrders
|
|
192
192
|
end
|
193
193
|
|
194
194
|
plans = plans.map do |plan|
|
195
|
+
description = ("$#{'%0.2f' % (plan.amount / 100.0)}" + ' ' + plan.currency.upcase + '/' + plan.interval.to_s)
|
196
|
+
|
195
197
|
{
|
196
198
|
id: plan.id,
|
197
199
|
product_id: plan.product,
|
198
|
-
name: plan.nickname,
|
200
|
+
name: plan.nickname || description,
|
201
|
+
description: description,
|
199
202
|
amount: plan.amount,
|
200
203
|
currency: plan.currency,
|
201
|
-
description: ("$#{'%0.2f' % (plan.amount / 100.0)}" + ' ' + plan.currency.upcase + '/' + plan.interval.to_s),
|
202
204
|
interval: plan.interval,
|
203
|
-
interval_count: plan.interval_count
|
205
|
+
interval_count: plan.interval_count,
|
206
|
+
trial_period_days: plan.trial_period_days
|
204
207
|
}
|
205
208
|
end.sort do |x, y|
|
206
209
|
val ||= (x[:interval] <=> y[:interval])
|
@@ -5,9 +5,9 @@ module EffectiveOrders
|
|
5
5
|
# Include acts_as_addressable concern and allow any ActiveRecord object to call it
|
6
6
|
initializer 'effective_orders.active_record' do |app|
|
7
7
|
ActiveSupport.on_load :active_record do
|
8
|
-
ActiveRecord::Base.extend(ActsAsPurchasable::
|
9
|
-
ActiveRecord::Base.extend(ActsAsSubscribable::
|
10
|
-
ActiveRecord::Base.extend(ActsAsSubscribableBuyer::
|
8
|
+
ActiveRecord::Base.extend(ActsAsPurchasable::Base)
|
9
|
+
ActiveRecord::Base.extend(ActsAsSubscribable::Base)
|
10
|
+
ActiveRecord::Base.extend(ActsAsSubscribableBuyer::Base)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
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.4.
|
4
|
+
version: 4.4.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -121,7 +121,7 @@ files:
|
|
121
121
|
- app/assets/images/effective_orders/stripe.png
|
122
122
|
- app/assets/javascripts/effective_orders.js
|
123
123
|
- app/assets/javascripts/effective_orders/customers.js.coffee
|
124
|
-
- app/assets/javascripts/effective_orders/providers/stripe.js
|
124
|
+
- app/assets/javascripts/effective_orders/providers/stripe.js.coffee
|
125
125
|
- app/assets/javascripts/effective_orders/subscriptions.js.coffee
|
126
126
|
- app/assets/stylesheets/effective_orders.scss
|
127
127
|
- app/assets/stylesheets/effective_orders/_cart.scss
|
@@ -253,7 +253,7 @@ homepage: https://github.com/code-and-effect/effective_orders
|
|
253
253
|
licenses:
|
254
254
|
- MIT
|
255
255
|
metadata: {}
|
256
|
-
post_install_message:
|
256
|
+
post_install_message:
|
257
257
|
rdoc_options: []
|
258
258
|
require_paths:
|
259
259
|
- lib
|
@@ -268,8 +268,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
268
268
|
- !ruby/object:Gem::Version
|
269
269
|
version: '0'
|
270
270
|
requirements: []
|
271
|
-
rubygems_version: 3.
|
272
|
-
signing_key:
|
271
|
+
rubygems_version: 3.1.2
|
272
|
+
signing_key:
|
273
273
|
specification_version: 4
|
274
274
|
summary: Quickly build an online store with carts, orders, automatic email receipts
|
275
275
|
and payment collection via Stripe, StripeConnect, PayPal and Moneris.
|
@@ -1,97 +0,0 @@
|
|
1
|
-
class StripeForm {
|
2
|
-
initialize() {
|
3
|
-
let $form = $('form[data-stripe-form]').first();
|
4
|
-
if ($form.length == 0) { return false; }
|
5
|
-
|
6
|
-
this.$form = $form;
|
7
|
-
this.$paymentIntentId = this.$form.find("input[name$='[payment_intent_id]']").first();
|
8
|
-
|
9
|
-
this.data = $form.data('stripe-form');
|
10
|
-
this.stripe = Stripe(this.data.key);
|
11
|
-
this.card = this.stripe.elements().create("card", { style: this.style() });
|
12
|
-
|
13
|
-
this.mount();
|
14
|
-
}
|
15
|
-
|
16
|
-
mount() {
|
17
|
-
this.card.mount("#stripe-card-element");
|
18
|
-
|
19
|
-
this.card.addEventListener('change', function ({ error }) {
|
20
|
-
if (error) {
|
21
|
-
$('#stripe-card-errors').text(error.message);
|
22
|
-
} else {
|
23
|
-
$('#stripe-card-errors').text('');
|
24
|
-
}
|
25
|
-
});
|
26
|
-
|
27
|
-
this.$form.on('click', '[type=submit]', (event) => { this.submit(event) });
|
28
|
-
}
|
29
|
-
|
30
|
-
shouldUseNewCard() {
|
31
|
-
let $newCardForm = this.$form.children('.collapse.show')
|
32
|
-
|
33
|
-
return (
|
34
|
-
this.$form.get(0).checkValidity() &&
|
35
|
-
(this.data.token_required || $newCardForm.length > 0) &&
|
36
|
-
this.$paymentIntentId.val().length == 0
|
37
|
-
)
|
38
|
-
}
|
39
|
-
|
40
|
-
submit(event) {
|
41
|
-
event.preventDefault();
|
42
|
-
|
43
|
-
let payment = this.shouldUseNewCard() ? this.useNewCard() : this.useExistingCard();
|
44
|
-
|
45
|
-
payment.then((result) => {
|
46
|
-
if (result.error) {
|
47
|
-
this.errorPayment(result.error)
|
48
|
-
} else if (result.paymentIntent.status == 'succeeded') {
|
49
|
-
this.submitPayment(result.paymentIntent);
|
50
|
-
}
|
51
|
-
});
|
52
|
-
}
|
53
|
-
|
54
|
-
useExistingCard() {
|
55
|
-
return this.stripe.confirmCardPayment(this.data.client_secret, {
|
56
|
-
payment_method: this.data.payment_method
|
57
|
-
});
|
58
|
-
}
|
59
|
-
|
60
|
-
useNewCard() {
|
61
|
-
return this.stripe.confirmCardPayment(this.data.client_secret, {
|
62
|
-
payment_method: {
|
63
|
-
card: this.card,
|
64
|
-
billing_details: {
|
65
|
-
email: this.data.email
|
66
|
-
}
|
67
|
-
},
|
68
|
-
setup_future_usage: 'off_session'
|
69
|
-
});
|
70
|
-
}
|
71
|
-
|
72
|
-
errorPayment(error) {
|
73
|
-
$('#stripe-card-errors').text(error.message);
|
74
|
-
EffectiveForm.invalidate(this.$form);
|
75
|
-
}
|
76
|
-
|
77
|
-
submitPayment(payment) {
|
78
|
-
this.$paymentIntentId.val('' + payment['id']);
|
79
|
-
this.$form.submit();
|
80
|
-
}
|
81
|
-
|
82
|
-
style() {
|
83
|
-
return {
|
84
|
-
base: {
|
85
|
-
color: "#32325d",
|
86
|
-
fontSize: "16px",
|
87
|
-
},
|
88
|
-
invalid: {
|
89
|
-
color: "#dc3545",
|
90
|
-
iconColor: "#dc3545"
|
91
|
-
}
|
92
|
-
};
|
93
|
-
}
|
94
|
-
|
95
|
-
}
|
96
|
-
|
97
|
-
$(document).ready(function () { new StripeForm().initialize(); });
|