effective_orders 2.2.4 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +124 -84
- data/app/assets/javascripts/effective_orders/customers.js.coffee +39 -0
- data/app/assets/javascripts/effective_orders/providers/{stripe_charges.js.coffee → stripe.js.coffee} +15 -13
- data/app/assets/javascripts/effective_orders/subscriptions.js.coffee +73 -0
- data/app/assets/stylesheets/effective_orders.scss +2 -1
- data/app/assets/stylesheets/effective_orders/_order.scss +16 -8
- data/app/assets/stylesheets/effective_orders/_subscriptions.scss +14 -0
- data/app/controllers/admin/customers_controller.rb +11 -8
- data/app/controllers/admin/order_items_controller.rb +4 -8
- data/app/controllers/admin/orders_controller.rb +133 -87
- data/app/controllers/effective/carts_controller.rb +18 -8
- data/app/controllers/effective/concerns/purchase.rb +39 -0
- data/app/controllers/effective/customers_controller.rb +43 -0
- data/app/controllers/effective/orders_controller.rb +73 -119
- data/app/controllers/effective/providers/app_checkout.rb +3 -1
- data/app/controllers/effective/providers/ccbill.rb +4 -6
- data/app/controllers/effective/providers/cheque.rb +20 -11
- data/app/controllers/effective/providers/free.rb +33 -0
- data/app/controllers/effective/providers/mark_as_paid.rb +33 -0
- data/app/controllers/effective/providers/moneris.rb +9 -17
- data/app/controllers/effective/providers/paypal.rb +4 -6
- data/app/controllers/effective/providers/pretend.rb +4 -4
- data/app/controllers/effective/providers/refund.rb +39 -0
- data/app/controllers/effective/providers/stripe.rb +19 -40
- data/app/controllers/effective/providers/stripe_connect.rb +2 -6
- data/app/controllers/effective/webhooks_controller.rb +44 -95
- data/app/datatables/effective_customers_datatable.rb +21 -29
- data/app/datatables/effective_order_items_datatable.rb +77 -79
- data/app/datatables/effective_orders_datatable.rb +67 -57
- data/app/helpers/effective_carts_helper.rb +17 -14
- data/app/helpers/effective_orders_helper.rb +40 -56
- data/app/helpers/effective_paypal_helper.rb +3 -3
- data/app/helpers/effective_stripe_helper.rb +47 -18
- data/app/helpers/effective_subscriptions_helper.rb +79 -0
- data/app/mailers/effective/orders_mailer.rb +125 -2
- data/app/models/concerns/acts_as_purchasable.rb +23 -33
- data/app/models/concerns/acts_as_subscribable.rb +68 -0
- data/app/models/concerns/acts_as_subscribable_buyer.rb +22 -0
- data/app/models/effective/cart.rb +53 -24
- data/app/models/effective/cart_item.rb +6 -12
- data/app/models/effective/customer.rb +51 -54
- data/app/models/effective/order.rb +160 -147
- data/app/models/effective/order_item.rb +18 -21
- data/app/models/effective/product.rb +7 -7
- data/app/models/effective/providers/ccbill_postback.rb +1 -1
- data/app/models/effective/providers/stripe_charge.rb +8 -19
- data/app/models/effective/subscripter.rb +230 -0
- data/app/models/effective/subscription.rb +27 -76
- data/app/models/effective/tax_rate_calculator.rb +10 -7
- data/app/views/admin/customers/_actions.html.haml +1 -2
- data/app/views/admin/customers/index.html.haml +1 -1
- data/app/views/admin/customers/show.html.haml +6 -0
- data/app/views/admin/orders/_actions.html.haml +9 -7
- data/app/views/admin/orders/_form.html.haml +11 -7
- data/app/views/admin/orders/_order_actions.html.haml +2 -1
- data/app/views/admin/orders/_order_item_fields.html.haml +1 -1
- data/app/views/admin/orders/edit.html.haml +4 -0
- data/app/views/admin/orders/index.html.haml +1 -4
- data/app/views/admin/orders/new.html.haml +1 -1
- data/app/views/admin/orders/show.html.haml +5 -6
- data/app/views/effective/carts/_cart.html.haml +2 -2
- data/app/views/effective/carts/show.html.haml +2 -2
- data/app/views/effective/customers/_customer.html.haml +152 -0
- data/app/views/effective/customers/_fields.html.haml +12 -0
- data/app/views/effective/customers/_form.html.haml +13 -0
- data/app/views/effective/customers/edit.html.haml +3 -0
- data/app/views/effective/orders/_checkout_step1.html.haml +8 -15
- data/app/views/effective/orders/_checkout_step2.html.haml +34 -21
- data/app/views/effective/orders/_order.html.haml +8 -9
- data/app/views/effective/orders/_order_actions.html.haml +7 -8
- data/app/views/effective/orders/_order_header.html.haml +1 -1
- data/app/views/effective/orders/_order_items.html.haml +11 -5
- data/app/views/effective/orders/_order_note.html.haml +4 -7
- data/app/views/effective/orders/_orders_table.html.haml +26 -26
- data/app/views/effective/orders/app_checkout/_form.html.haml +2 -2
- data/app/views/effective/orders/ccbill/_form.html.haml +1 -1
- data/app/views/effective/orders/cheque/_form.html.haml +3 -1
- data/app/views/effective/orders/declined.html.haml +1 -1
- data/app/views/effective/orders/{checkout_step1.html.haml → edit.html.haml} +0 -0
- data/app/views/effective/orders/free/_form.html.haml +4 -0
- data/app/views/effective/orders/index.html.haml +2 -4
- data/app/views/effective/orders/mark_as_paid/_form.html.haml +32 -0
- data/app/views/effective/orders/moneris/_form.html.haml +6 -6
- data/app/views/effective/orders/{checkout_step2.html.haml → new.html.haml} +1 -1
- data/app/views/effective/orders/paypal/_form.html.haml +2 -2
- data/app/views/effective/orders/pretend/_form.html.haml +2 -2
- data/app/views/effective/orders/purchased.html.haml +3 -0
- data/app/views/effective/orders/refund/_form.html.haml +32 -0
- data/app/views/effective/orders/show.html.haml +4 -1
- data/app/views/effective/orders/stripe/_form.html.haml +5 -5
- data/app/views/effective/orders_mailer/subscription_canceled.html.haml +9 -0
- data/app/views/effective/orders_mailer/subscription_payment_failed.html.haml +9 -0
- data/app/views/effective/orders_mailer/subscription_payment_succeeded.html.haml +9 -0
- data/app/views/effective/orders_mailer/subscription_trial_expired.html.haml +5 -0
- data/app/views/effective/orders_mailer/subscription_trial_expiring.html.haml +7 -0
- data/app/views/effective/subscriptions/_fields.html.haml +16 -0
- data/app/views/effective/subscriptions/_plan.html.haml +21 -0
- data/app/views/layouts/effective_orders_mailer_layout.html.haml +6 -8
- data/config/effective_orders.rb +41 -20
- data/config/routes.rb +48 -48
- data/db/migrate/01_create_effective_orders.rb.erb +19 -5
- data/lib/effective_orders.rb +78 -42
- data/lib/effective_orders/engine.rb +36 -82
- data/lib/effective_orders/version.rb +1 -1
- data/lib/generators/effective_orders/install_generator.rb +2 -2
- data/lib/generators/templates/effective_orders_mailer_preview.rb +39 -4
- data/lib/tasks/effective_orders_tasks.rake +42 -0
- data/spec/controllers/carts_controller_spec.rb +1 -1
- data/spec/controllers/moneris_orders_controller_spec.rb +4 -4
- data/spec/controllers/orders_controller_spec.rb +4 -4
- data/spec/controllers/stripe_orders_controller_spec.rb +2 -2
- data/spec/controllers/webhooks_controller_spec.rb +1 -1
- data/spec/dummy/config/initializers/effective_orders.rb +1 -7
- data/spec/dummy/db/schema.rb +1 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/test.log +3 -0
- data/spec/models/acts_as_purchasable_spec.rb +0 -56
- data/spec/models/customer_spec.rb +3 -3
- data/spec/models/order_spec.rb +2 -2
- data/spec/spec_helper.rb +1 -1
- data/spec/support/factories.rb +2 -1
- metadata +37 -49
- data/active_admin/effective_carts.rb +0 -14
- data/active_admin/effective_orders.rb +0 -112
- data/app/assets/javascripts/effective_orders/providers/stripe_subscriptions.js.coffee +0 -28
- data/app/controllers/concerns/acts_as_active_admin_controller.rb +0 -69
- data/app/controllers/effective/subscriptions_controller.rb +0 -126
- data/app/models/effective/datatables/customers.rb +0 -40
- data/app/models/effective/datatables/order_items.rb +0 -101
- data/app/models/effective/datatables/orders.rb +0 -91
- data/app/models/inputs/price_field.rb +0 -63
- data/app/models/inputs/price_form_input.rb +0 -7
- data/app/models/inputs/price_formtastic_input.rb +0 -9
- data/app/models/inputs/price_input.rb +0 -19
- data/app/models/inputs/price_simple_form_input.rb +0 -8
- data/app/views/admin/orders/_form_mark_as_paid.html.haml +0 -33
- data/app/views/admin/orders/_order_payment_details.html.haml +0 -5
- data/app/views/admin/orders/mark_as_paid.html.haml +0 -7
- data/app/views/effective/orders/stripe/_subscription_fields.html.haml +0 -7
- data/app/views/effective/subscriptions/index.html.haml +0 -22
- data/app/views/effective/subscriptions/new.html.haml +0 -9
- data/app/views/effective/subscriptions/show.html.haml +0 -49
- data/db/upgrade/02_upgrade_effective_orders_from03x.rb.erb +0 -29
- data/db/upgrade/03_upgrade_effective_orders_from1x.rb.erb +0 -98
- data/db/upgrade/upgrade_price_column_on_table.rb.erb +0 -17
- data/lib/generators/effective_orders/upgrade_from03x_generator.rb +0 -31
- data/lib/generators/effective_orders/upgrade_from1x_generator.rb +0 -27
- data/lib/generators/effective_orders/upgrade_price_column_generator.rb +0 -30
@@ -1,8 +1,8 @@
|
|
1
1
|
module EffectiveOrdersHelper
|
2
|
-
def price_to_currency(price
|
3
|
-
|
4
|
-
|
5
|
-
number_to_currency(price / 100.0
|
2
|
+
def price_to_currency(price)
|
3
|
+
price = price || 0
|
4
|
+
raise 'price_to_currency expects an Integer representing the number of cents' unless price.kind_of?(Integer)
|
5
|
+
number_to_currency(price / 100.0)
|
6
6
|
end
|
7
7
|
|
8
8
|
def tax_rate_to_percentage(tax_rate, options = {})
|
@@ -33,11 +33,15 @@ module EffectiveOrdersHelper
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def order_checkout_label(processor = nil)
|
36
|
-
return 'Checkout' if (EffectiveOrders.single_payment_processor? &&
|
36
|
+
return 'Checkout' if (EffectiveOrders.single_payment_processor? && ![:pretend, :mark_as_paid, :free, :refund].include?(processor))
|
37
37
|
|
38
38
|
case processor
|
39
|
+
when :mark_as_paid
|
40
|
+
'Mark as paid'
|
39
41
|
when :free
|
40
|
-
'Checkout'
|
42
|
+
'Checkout free'
|
43
|
+
when :refund
|
44
|
+
'Complete refund'
|
41
45
|
when :moneris, :stripe, :ccbill
|
42
46
|
'Checkout with credit card'
|
43
47
|
when :paypal
|
@@ -45,7 +49,7 @@ module EffectiveOrdersHelper
|
|
45
49
|
when :pretend
|
46
50
|
EffectiveOrders.allow_pretend_purchase_in_production ? 'Purchase Order' : 'Purchase Order (development only)'
|
47
51
|
when :cheque
|
48
|
-
'Pay by
|
52
|
+
'Pay by cheque'
|
49
53
|
when :app_checkout
|
50
54
|
EffectiveOrders.app_checkout[:checkout_label].presence || 'Checkout'
|
51
55
|
else
|
@@ -82,27 +86,38 @@ module EffectiveOrdersHelper
|
|
82
86
|
end
|
83
87
|
|
84
88
|
def render_order(order)
|
85
|
-
render(partial: 'effective/orders/order', locals: {order: order})
|
89
|
+
render(partial: 'effective/orders/order', locals: { order: order })
|
86
90
|
end
|
87
91
|
|
88
|
-
def render_checkout_step1(order,
|
89
|
-
raise
|
92
|
+
def render_checkout_step1(order, namespace: nil, purchased_url: nil, declined_url: nil)
|
93
|
+
raise 'unable to checkout an order without a user' unless order && order.user
|
90
94
|
|
91
|
-
locals = {
|
95
|
+
locals = { order: order, purchased_url: purchased_url, declined_url: declined_url, namespace: namespace }
|
92
96
|
|
93
|
-
render
|
97
|
+
render partial: 'effective/orders/checkout_step1', locals: locals
|
94
98
|
end
|
95
99
|
alias_method :render_checkout, :render_checkout_step1
|
96
100
|
|
97
|
-
def render_checkout_step2(order,
|
98
|
-
raise
|
101
|
+
def render_checkout_step2(order, namespace: nil, purchased_url: nil, declined_url: nil)
|
102
|
+
raise 'unable to checkout an order without a user' unless order && order.user
|
99
103
|
|
100
|
-
locals = {
|
104
|
+
locals = { order: order, purchased_url: purchased_url, declined_url: declined_url, namespace: namespace }
|
101
105
|
|
102
106
|
if order.new_record? || !order.valid?
|
103
|
-
render(partial: 'effective/orders/checkout_step1', locals: locals
|
107
|
+
render(partial: 'effective/orders/checkout_step1', locals: locals)
|
108
|
+
else
|
109
|
+
render(partial: 'effective/orders/checkout_step2', locals: locals)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def checkout_step1_form_url(order, namespace = nil)
|
114
|
+
raise 'expected an order' unless order
|
115
|
+
raise 'invalid namespace, expecting nil or :admin' unless [nil, :admin].include?(namespace)
|
116
|
+
|
117
|
+
if order.new_record?
|
118
|
+
namespace == nil ? effective_orders.orders_path : effective_orders.admin_orders_path
|
104
119
|
else
|
105
|
-
|
120
|
+
namespace == nil ? effective_orders.order_path(order) : effective_orders.checkout_admin_order_path(order)
|
106
121
|
end
|
107
122
|
end
|
108
123
|
|
@@ -116,56 +131,25 @@ module EffectiveOrdersHelper
|
|
116
131
|
label = options.delete(:label)
|
117
132
|
options[:class] = ((options[:class] || '') + ' btn-my-purchases')
|
118
133
|
|
119
|
-
link_to(label, effective_orders.
|
134
|
+
link_to(label, effective_orders.my_purchases_orders_path, options)
|
120
135
|
end
|
121
136
|
alias_method :link_to_order_history, :link_to_my_purchases
|
122
137
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
raise ArgumentError.new('expecting an instance of User or an array/collection of Effective::Order objects')
|
138
|
+
|
139
|
+
def render_orders(obj, opts = {})
|
140
|
+
orders = Array(obj.kind_of?(User) ? Effective::Order.purchased_by(obj) : obj)
|
141
|
+
|
142
|
+
if orders.any? { |order| order.kind_of?(Effective::Order) == false }
|
143
|
+
raise 'expected a User or Effective::Order'
|
130
144
|
end
|
131
145
|
|
132
|
-
render(partial: 'effective/orders/orders_table', locals: {orders: orders}.merge(opts))
|
146
|
+
render(partial: 'effective/orders/orders_table', locals: { orders: orders }.merge(opts))
|
133
147
|
end
|
134
148
|
|
135
149
|
alias_method :render_purchases, :render_orders
|
136
150
|
alias_method :render_my_purchases, :render_orders
|
137
151
|
alias_method :render_order_history, :render_orders
|
138
152
|
|
139
|
-
# Used by the _payment_details partial
|
140
|
-
def tableize_order_payment(hash, options = {class: 'table table-bordered'})
|
141
|
-
if hash.present? && hash.kind_of?(Hash)
|
142
|
-
content_tag(:table, class: options[:class]) do
|
143
|
-
title = options.delete(:title)
|
144
|
-
|
145
|
-
content = content_tag(:tbody) do
|
146
|
-
hash.map do |k, v|
|
147
|
-
content_tag(:tr) do
|
148
|
-
content_tag((options[:th] ? :th : :td), k) +
|
149
|
-
content_tag(:td) do
|
150
|
-
if v.kind_of?(Hash)
|
151
|
-
tableize_order_payment(v, options.merge(th: (options.key?(:sub_th) ? options[:sub_th] : options[:th])))
|
152
|
-
elsif v.kind_of?(Array)
|
153
|
-
'[' + v.join(', ') + ']'
|
154
|
-
else
|
155
|
-
v
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end.join.html_safe
|
160
|
-
end
|
161
|
-
|
162
|
-
title.blank? ? content : (content_tag(:thead) { content_tag(:tr) { content_tag(:th, title, colspan: 2) } } + content)
|
163
|
-
end
|
164
|
-
else
|
165
|
-
hash.to_s.html_safe
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
153
|
def payment_card_label(card)
|
170
154
|
card = card.to_s.downcase.gsub(' ', '').strip
|
171
155
|
|
@@ -15,9 +15,9 @@ module EffectivePaypalHelper
|
|
15
15
|
APP_KEY_PEM = ConfigReader.cert_or_key(:app_key)
|
16
16
|
|
17
17
|
def paypal_encrypted_payload(order)
|
18
|
-
raise
|
19
|
-
raise
|
20
|
-
raise
|
18
|
+
raise "unable to read EffectiveOrders PayPal paypal_cert #{EffectiveOrders.paypal[:paypal_cert]}" unless PAYPAL_CERT_PEM.present?
|
19
|
+
raise "unable to read EffectiveOrders PayPal app_cert #{EffectiveOrders.paypal[:app_cert]}" unless APP_CERT_PEM.present?
|
20
|
+
raise "unable to read EffectiveOrders PayPal app_key #{EffectiveOrders.paypal[:app_key]}" unless APP_KEY_PEM.present?
|
21
21
|
|
22
22
|
values = {
|
23
23
|
business: EffectiveOrders.paypal[:seller_email],
|
@@ -4,13 +4,13 @@ module EffectiveStripeHelper
|
|
4
4
|
STRIPE_CONNECT_TOKEN_URL = 'https://connect.stripe.com/oauth/token'
|
5
5
|
|
6
6
|
def is_stripe_connect_seller?(user)
|
7
|
-
Effective::Customer.
|
7
|
+
Effective::Customer.for_buyer(user).stripe_connect_access_token.present?
|
8
8
|
end
|
9
9
|
|
10
10
|
def link_to_new_stripe_connect_customer(opts = {})
|
11
11
|
client_id = EffectiveOrders.stripe[:connect_client_id]
|
12
12
|
|
13
|
-
raise
|
13
|
+
raise 'effective_orders config: stripe.connect_client_id has not been set' unless client_id.present?
|
14
14
|
|
15
15
|
authorize_params = {
|
16
16
|
response_type: :code,
|
@@ -26,28 +26,35 @@ module EffectiveStripeHelper
|
|
26
26
|
stripe_user_params = opts.delete :stripe_user
|
27
27
|
authorize_params.merge!({stripe_user: stripe_user_params}) if stripe_user_params.is_a?(Hash)
|
28
28
|
|
29
|
-
authorize_url = STRIPE_CONNECT_AUTHORIZE_URL
|
29
|
+
authorize_url = STRIPE_CONNECT_AUTHORIZE_URL + '?' + authorize_params.to_query
|
30
30
|
options = {}.merge(opts)
|
31
31
|
link_to image_tag('/assets/effective_orders/stripe_connect.png'), authorize_url, options
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
def stripe_plan_description(obj)
|
35
|
+
plan = (
|
36
|
+
case obj
|
37
|
+
when Hash ; obj
|
38
|
+
when ::Stripe::Plan ; EffectiveOrders.stripe_plans.find { |plan| plan.id == obj.id }
|
39
|
+
else ; raise 'unexpected object'
|
40
|
+
end
|
41
|
+
)
|
38
42
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
when 'yearly' ; '/year'
|
44
|
-
when 'week' ; plan.interval_count == 1 ? '/week' : " every #{plan.interval_count} weeks"
|
45
|
-
when 'month' ; plan.interval_count == 1 ? '/month' : " every #{plan.interval_count} months"
|
46
|
-
when 'year' ; plan.interval_count == 1 ? '/year' : " every #{plan.interval_count} years"
|
47
|
-
else ; plan.interval
|
48
|
-
end
|
43
|
+
raise("unknown stripe plan: #{obj}") unless plan.kind_of?(Hash) && plan[:id].present?
|
44
|
+
|
45
|
+
plan[:description]
|
46
|
+
end
|
49
47
|
|
50
|
-
|
48
|
+
def stripe_invoice_line_description(line, simple: false)
|
49
|
+
[
|
50
|
+
"#{line.quantity}x",
|
51
|
+
line.plan.name,
|
52
|
+
price_to_currency(line.amount),
|
53
|
+
("#{Time.zone.at(line.period.start).strftime('%F')}" unless simple),
|
54
|
+
('to' unless simple),
|
55
|
+
("#{Time.zone.at(line.period.end).strftime('%F')}" unless simple),
|
56
|
+
line.description.presence
|
57
|
+
].compact.join(' ')
|
51
58
|
end
|
52
59
|
|
53
60
|
def stripe_coupon_description(coupon)
|
@@ -60,4 +67,26 @@ module EffectiveStripeHelper
|
|
60
67
|
end
|
61
68
|
end
|
62
69
|
|
70
|
+
def stripe_site_image_url
|
71
|
+
return nil unless EffectiveOrders.stripe && (url = EffectiveOrders.stripe[:site_image].to_s).present?
|
72
|
+
url.start_with?('http') ? url : asset_url(url)
|
73
|
+
end
|
74
|
+
|
75
|
+
def stripe_order_description(order)
|
76
|
+
"#{order.num_items} items (#{price_to_currency(order.total)})"
|
77
|
+
end
|
78
|
+
|
79
|
+
def stripe_charge_data(order)
|
80
|
+
{
|
81
|
+
stripe: {
|
82
|
+
key: EffectiveOrders.stripe[:publishable_key],
|
83
|
+
name: EffectiveOrders.stripe[:site_title],
|
84
|
+
image: stripe_site_image_url,
|
85
|
+
email: order.user.email,
|
86
|
+
amount: order.total,
|
87
|
+
description: stripe_order_description(order)
|
88
|
+
}.to_json
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
63
92
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module EffectiveSubscriptionsHelper
|
2
|
+
|
3
|
+
def effective_customer_fields(form, submit: true)
|
4
|
+
raise 'expected a SimpleForm::FormBuilder object' unless form.class.name == 'SimpleForm::FormBuilder'
|
5
|
+
raise 'form object must be an Effective::Subscripter object' unless form.object.class.name == 'Effective::Subscripter'
|
6
|
+
|
7
|
+
render(
|
8
|
+
partial: 'effective/customers/fields',
|
9
|
+
locals: {
|
10
|
+
f: form,
|
11
|
+
submit: submit,
|
12
|
+
stripe: {
|
13
|
+
email: form.object.customer.user.email,
|
14
|
+
image: stripe_site_image_url,
|
15
|
+
key: EffectiveOrders.stripe[:publishable_key],
|
16
|
+
name: EffectiveOrders.stripe[:site_title],
|
17
|
+
}
|
18
|
+
}
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def stripe_plans_collection(form, include_trial: nil, selected_class: 'selected panel-primary')
|
23
|
+
raise 'expected a SimpleForm::FormBuilder object' unless form.class.name == 'SimpleForm::FormBuilder'
|
24
|
+
raise 'form object must be an acts_as_subscribable object' unless form.object.subscribable.subscripter.present?
|
25
|
+
|
26
|
+
include_trial = form.object.subscribable.subscribed?('trial') if include_trial.nil?
|
27
|
+
|
28
|
+
plans = include_trial ? EffectiveOrders.stripe_plans : EffectiveOrders.stripe_plans.except('trial')
|
29
|
+
plans = plans.values.sort { |x, y| (amount = x[:amount] <=> y[:amount]) != 0 ? amount : x[:name] <=> y[:name] }
|
30
|
+
|
31
|
+
plans.map do |plan|
|
32
|
+
partial = (
|
33
|
+
if lookup_context.template_exists?("effective/subscriptions/#{plan[:id].downcase}", [], true)
|
34
|
+
"effective/subscriptions/#{plan[:id].downcase}" # Render the app's views/effective/subscriptions/_gold.html.haml
|
35
|
+
else
|
36
|
+
'effective/subscriptions/plan' # Render effective_orders default plan panel
|
37
|
+
end
|
38
|
+
)
|
39
|
+
|
40
|
+
content = render(partial: partial, locals: {
|
41
|
+
f: form,
|
42
|
+
plan: plan,
|
43
|
+
selected: Array(form.object.stripe_plan_id).include?(plan[:id]),
|
44
|
+
selected_class: selected_class,
|
45
|
+
subscribable: form.object.subscribable,
|
46
|
+
subscribed: form.object.subscribable.subscribed?(plan[:id])
|
47
|
+
})
|
48
|
+
|
49
|
+
[content, plan[:id]]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def effective_subscription_fields(form, label: false, required: true, include_trial: nil, item_wrapper_class: 'col-sm-6 col-md-4 col-lg-3', selected_class: 'selected panel-primary', wrapper_class: 'row')
|
54
|
+
raise 'expected a SimpleForm::FormBuilder object' unless form.class.name == 'SimpleForm::FormBuilder'
|
55
|
+
raise 'form object must be an acts_as_subscribable object' unless form.object.subscripter.present?
|
56
|
+
|
57
|
+
render(
|
58
|
+
partial: 'effective/subscriptions/fields',
|
59
|
+
locals: {
|
60
|
+
form: form,
|
61
|
+
label: label,
|
62
|
+
required: required,
|
63
|
+
include_trial: include_trial,
|
64
|
+
item_wrapper_class: item_wrapper_class,
|
65
|
+
selected_class: selected_class,
|
66
|
+
stripe: {
|
67
|
+
email: form.object.buyer.email,
|
68
|
+
image: stripe_site_image_url,
|
69
|
+
key: EffectiveOrders.stripe[:publishable_key],
|
70
|
+
name: EffectiveOrders.stripe[:site_title],
|
71
|
+
plans: EffectiveOrders.stripe_plans.values,
|
72
|
+
token_required: form.object.subscripter.token_required?
|
73
|
+
},
|
74
|
+
wrapper_class: wrapper_class
|
75
|
+
}
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -5,6 +5,8 @@ module Effective
|
|
5
5
|
layout EffectiveOrders.mailer[:layout].presence || 'effective_orders_mailer_layout'
|
6
6
|
|
7
7
|
def order_receipt_to_admin(order_param)
|
8
|
+
return true unless EffectiveOrders.mailer[:send_order_receipt_to_admin]
|
9
|
+
|
8
10
|
@order = (order_param.kind_of?(Effective::Order) ? order_param : Effective::Order.find(order_param))
|
9
11
|
|
10
12
|
mail(
|
@@ -15,6 +17,8 @@ module Effective
|
|
15
17
|
end
|
16
18
|
|
17
19
|
def order_receipt_to_buyer(order_param) # Buyer
|
20
|
+
return true unless EffectiveOrders.mailer[:send_order_receipt_to_buyer]
|
21
|
+
|
18
22
|
@order = (order_param.kind_of?(Effective::Order) ? order_param : Effective::Order.find(order_param))
|
19
23
|
|
20
24
|
mail(
|
@@ -25,6 +29,8 @@ module Effective
|
|
25
29
|
end
|
26
30
|
|
27
31
|
def order_receipt_to_seller(order_param, seller, order_items)
|
32
|
+
return true unless EffectiveOrders.mailer[:send_order_receipt_to_seller]
|
33
|
+
|
28
34
|
@order = (order_param.kind_of?(Effective::Order) ? order_param : Effective::Order.find(order_param))
|
29
35
|
@user = seller.user
|
30
36
|
@order_items = order_items
|
@@ -40,6 +46,8 @@ module Effective
|
|
40
46
|
# This is sent when an admin creates a new order or /admin/orders/new
|
41
47
|
# Or uses the order action Send Payment Request
|
42
48
|
def payment_request_to_buyer(order_param)
|
49
|
+
return true unless EffectiveOrders.mailer[:send_payment_request_to_buyer]
|
50
|
+
|
43
51
|
@order = (order_param.kind_of?(Effective::Order) ? order_param : Effective::Order.find(order_param))
|
44
52
|
|
45
53
|
mail(
|
@@ -51,6 +59,8 @@ module Effective
|
|
51
59
|
|
52
60
|
# This is sent when someone chooses to Pay by Cheque
|
53
61
|
def pending_order_invoice_to_buyer(order_param)
|
62
|
+
return true unless EffectiveOrders.mailer[:send_pending_order_invoice_to_buyer]
|
63
|
+
|
54
64
|
@order = (order_param.kind_of?(Effective::Order) ? order_param : Effective::Order.find(order_param))
|
55
65
|
|
56
66
|
mail(
|
@@ -60,6 +70,71 @@ module Effective
|
|
60
70
|
)
|
61
71
|
end
|
62
72
|
|
73
|
+
# Sent by the invoice.payment_succeeded webhook event
|
74
|
+
def subscription_payment_succeeded(customer_param)
|
75
|
+
return true unless EffectiveOrders.mailer[:send_subscription_payment_succeeded]
|
76
|
+
|
77
|
+
@customer = (customer_param.kind_of?(Effective::Customer) ? customer_param : Effective::Customer.find(customer_param))
|
78
|
+
|
79
|
+
mail(
|
80
|
+
to: @customer.user.email,
|
81
|
+
from: EffectiveOrders.mailer[:default_from],
|
82
|
+
subject: subject_for_subscription_payment_succeeded(@customer)
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Sent by the invoice.payment_failed webhook event
|
87
|
+
def subscription_payment_failed(customer_param)
|
88
|
+
return true unless EffectiveOrders.mailer[:send_subscription_payment_failed]
|
89
|
+
|
90
|
+
@customer = (customer_param.kind_of?(Effective::Customer) ? customer_param : Effective::Customer.find(customer_param))
|
91
|
+
|
92
|
+
mail(
|
93
|
+
to: @customer.user.email,
|
94
|
+
from: EffectiveOrders.mailer[:default_from],
|
95
|
+
subject: subject_for_subscription_payment_failed(@customer)
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Sent by the invoice.payment_failed webhook event
|
100
|
+
def subscription_canceled(customer_param)
|
101
|
+
return true unless EffectiveOrders.mailer[:send_subscription_canceled]
|
102
|
+
|
103
|
+
@customer = (customer_param.kind_of?(Effective::Customer) ? customer_param : Effective::Customer.find(customer_param))
|
104
|
+
|
105
|
+
mail(
|
106
|
+
to: @customer.user.email,
|
107
|
+
from: EffectiveOrders.mailer[:default_from],
|
108
|
+
subject: subject_for_subscription_canceled(@customer)
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Sent by the effective_orders:notify_trial_users rake task.
|
113
|
+
def subscription_trial_expiring(subscribable)
|
114
|
+
return true unless EffectiveOrders.mailer[:send_subscription_trial_expiring]
|
115
|
+
|
116
|
+
@subscribable = subscribable
|
117
|
+
|
118
|
+
mail(
|
119
|
+
to: @subscribable.buyer.email,
|
120
|
+
from: EffectiveOrders.mailer[:default_from],
|
121
|
+
subject: subject_for_subscription_trial_expiring(@subscribable)
|
122
|
+
)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Sent by the effective_orders:notify_trial_users rake task.
|
126
|
+
def subscription_trial_expired(subscribable)
|
127
|
+
return true unless EffectiveOrders.mailer[:send_subscription_trial_expired]
|
128
|
+
|
129
|
+
@subscribable = subscribable
|
130
|
+
|
131
|
+
mail(
|
132
|
+
to: @subscribable.buyer.email,
|
133
|
+
from: EffectiveOrders.mailer[:default_from],
|
134
|
+
subject: subject_for_subscription_trial_expired(@subscribable)
|
135
|
+
)
|
136
|
+
end
|
137
|
+
|
63
138
|
def order_error(order: nil, error: nil, to: nil, from: nil, subject: nil, template: 'order_error')
|
64
139
|
if order.present?
|
65
140
|
@order = (order.kind_of?(Effective::Order) ? order : Effective::Order.find(order))
|
@@ -77,7 +152,6 @@ module Effective
|
|
77
152
|
) do |format|
|
78
153
|
format.html { render(template) }
|
79
154
|
end
|
80
|
-
|
81
155
|
end
|
82
156
|
|
83
157
|
private
|
@@ -103,7 +177,7 @@ module Effective
|
|
103
177
|
end
|
104
178
|
|
105
179
|
def subject_for_order_receipt_to_seller(order, order_items, seller)
|
106
|
-
string_or_callable = EffectiveOrders.mailer[:
|
180
|
+
string_or_callable = EffectiveOrders.mailer[:subject_for_order_receipt_to_seller]
|
107
181
|
|
108
182
|
if string_or_callable.respond_to?(:call) # This is a Proc or a function, not a string
|
109
183
|
string_or_callable = self.instance_exec(order, order_items, seller, &string_or_callable)
|
@@ -132,6 +206,55 @@ module Effective
|
|
132
206
|
prefix_subject(string_or_callable.presence || "Pending Order: ##{order.to_param}")
|
133
207
|
end
|
134
208
|
|
209
|
+
def subject_for_subscription_payment_succeeded(customer)
|
210
|
+
string_or_callable = EffectiveOrders.mailer[:subject_for_subscription_payment_succeeded]
|
211
|
+
|
212
|
+
if string_or_callable.respond_to?(:call) # This is a Proc or a function, not a string
|
213
|
+
string_or_callable = self.instance_exec(order, &string_or_callable)
|
214
|
+
end
|
215
|
+
|
216
|
+
prefix_subject(string_or_callable.presence || 'Thank you for your payment')
|
217
|
+
end
|
218
|
+
|
219
|
+
def subject_for_subscription_payment_failed(customer)
|
220
|
+
string_or_callable = EffectiveOrders.mailer[:subject_for_subscription_payment_failed]
|
221
|
+
|
222
|
+
if string_or_callable.respond_to?(:call) # This is a Proc or a function, not a string
|
223
|
+
string_or_callable = self.instance_exec(order, &string_or_callable)
|
224
|
+
end
|
225
|
+
|
226
|
+
prefix_subject(string_or_callable.presence || 'Payment failed - please update your card details')
|
227
|
+
end
|
228
|
+
|
229
|
+
def subject_for_subscription_canceled(customer)
|
230
|
+
string_or_callable = EffectiveOrders.mailer[:subject_for_subscription_canceled]
|
231
|
+
|
232
|
+
if string_or_callable.respond_to?(:call) # This is a Proc or a function, not a string
|
233
|
+
string_or_callable = self.instance_exec(order, &string_or_callable)
|
234
|
+
end
|
235
|
+
|
236
|
+
prefix_subject(string_or_callable.presence || 'Subscription canceled')
|
237
|
+
end
|
238
|
+
|
239
|
+
def subject_for_subscription_trial_expiring(customer)
|
240
|
+
string_or_callable = EffectiveOrders.mailer[:subject_for_subscription_trial_expiring]
|
241
|
+
|
242
|
+
if string_or_callable.respond_to?(:call) # This is a Proc or a function, not a string
|
243
|
+
string_or_callable = self.instance_exec(order, &string_or_callable)
|
244
|
+
end
|
245
|
+
|
246
|
+
prefix_subject(string_or_callable.presence || 'Trial expiring soon')
|
247
|
+
end
|
248
|
+
|
249
|
+
def subject_for_subscription_trial_expired(customer)
|
250
|
+
string_or_callable = EffectiveOrders.mailer[:subject_for_subscription_trial_expired]
|
251
|
+
|
252
|
+
if string_or_callable.respond_to?(:call) # This is a Proc or a function, not a string
|
253
|
+
string_or_callable = self.instance_exec(order, &string_or_callable)
|
254
|
+
end
|
255
|
+
|
256
|
+
prefix_subject(string_or_callable.presence || 'Trial expired')
|
257
|
+
end
|
135
258
|
|
136
259
|
def prefix_subject(text)
|
137
260
|
prefix = (EffectiveOrders.mailer[:subject_prefix].to_s rescue '')
|