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
@@ -2,26 +2,24 @@
|
|
2
2
|
%html{style: 'background: #fff;'}
|
3
3
|
%head
|
4
4
|
%meta{:content => 'text/html; charset=UTF-8', 'http-equiv' => 'Content-Type'}
|
5
|
+
|
5
6
|
:css
|
6
|
-
.effective-order table.table { min-width: 650px; }
|
7
|
+
.effective-order table.table { min-width: 650px; vertical-align: top; border: 0; }
|
8
|
+
.effective-order table.table td { border: 0; vertical-align: top; }
|
7
9
|
.effective-order { text-align: left; }
|
8
10
|
.effective-order .price { text-align: right; }
|
9
11
|
.effective-order tfoot th { text-align: right; }
|
10
12
|
.effective-order tfoot tr:first-child td { padding-top: 24px; }
|
11
13
|
.effective-order tfoot tr:first-child th { padding-top: 24px; }
|
12
14
|
.effective-order-shipping { padding-top: 12px; padding-bottom: 12px; }
|
15
|
+
.effective-order-header h1 { margin: 0; }
|
16
|
+
@media print { .effective-page-break { page-break-inside: avoid; page-break-after: always; min-height: 1px; } }
|
13
17
|
|
14
18
|
%body{style: 'background: #fff;'}
|
15
19
|
%table{style: 'width: 100%;'}
|
16
20
|
%tr
|
17
21
|
%td
|
18
22
|
%table{style: 'max-width: 650px; margin: 4px auto 30px;'}
|
19
|
-
%
|
20
|
-
%tr
|
21
|
-
%th
|
22
|
-
%tbody{style: 'width: 100%'}
|
23
|
+
%tbody{style: 'width: 100%;'}
|
23
24
|
%tr
|
24
25
|
%td= yield
|
25
|
-
%tfoot{style: 'width: 100%;'}
|
26
|
-
%tr
|
27
|
-
%th
|
data/config/effective_orders.rb
CHANGED
@@ -10,7 +10,6 @@ EffectiveOrders.setup do |config|
|
|
10
10
|
config.subscriptions_table_name = :subscriptions
|
11
11
|
config.products_table_name = :products
|
12
12
|
|
13
|
-
|
14
13
|
# Authorization Method
|
15
14
|
#
|
16
15
|
# This method is called by all controller actions with the appropriate action and resource
|
@@ -38,18 +37,9 @@ EffectiveOrders.setup do |config|
|
|
38
37
|
# Filter the @orders on admin/orders#index screen
|
39
38
|
# config.orders_collection_scope = Proc.new { |scope| scope.where(...) }
|
40
39
|
|
41
|
-
# Register Effective::Order with ActiveAdmin if ActiveAdmin is present
|
42
|
-
# You must have authorization to authorized?(:manage, Effective::Order)
|
43
|
-
# For the activeadmin menu to item to show up
|
44
|
-
config.use_active_admin = true
|
45
|
-
config.active_admin_namespace = :admin # Passed internally to ActiveAdmin.register
|
46
|
-
|
47
40
|
# Use effective_obfuscation gem to change order.id into a seemingly random 10-digit number
|
48
41
|
config.obfuscate_order_ids = false
|
49
42
|
|
50
|
-
# Silence the price deprecation warnings
|
51
|
-
config.silence_deprecation_warnings = false
|
52
|
-
|
53
43
|
# Require these addresses when creating a new Order. Works with effective_addresses gem
|
54
44
|
config.require_billing_address = true
|
55
45
|
config.require_shipping_address = false
|
@@ -95,10 +85,15 @@ EffectiveOrders.setup do |config|
|
|
95
85
|
|
96
86
|
# Free Orders
|
97
87
|
# Allow orders with a total of 0.00 to be purchased (regardless of the minimum charge setting)
|
98
|
-
# When enabled, the checkout process will skip the paypal/stripe/purchasing step
|
99
88
|
# and just display the 'Thank You' after checkout is clicked
|
100
89
|
config.allow_free_orders = true
|
101
90
|
|
91
|
+
# Refunds
|
92
|
+
# Allow admins to create orders with a negative total
|
93
|
+
# Refunds don't perform any kind of refund action with the payment processor.
|
94
|
+
# This just changes the validations
|
95
|
+
config.allow_refunds = false
|
96
|
+
|
102
97
|
# Display a 'Purchase order' button on the Checkout screen allowing the user
|
103
98
|
# to purchase an Order without going through the payment processor
|
104
99
|
config.allow_pretend_purchase_in_development = true
|
@@ -137,12 +132,12 @@ EffectiveOrders.setup do |config|
|
|
137
132
|
config.admin_simple_form_options = {} # For the /admin/orders/new form
|
138
133
|
|
139
134
|
# config.simple_form_options = {
|
140
|
-
# html
|
141
|
-
# wrapper
|
142
|
-
# wrapper_mappings
|
143
|
-
# boolean
|
144
|
-
# check_boxes
|
145
|
-
# radio_buttons
|
135
|
+
# :html => {:class => ['form-horizontal']},
|
136
|
+
# :wrapper => :horizontal_form,
|
137
|
+
# :wrapper_mappings => {
|
138
|
+
# :boolean => :horizontal_boolean,
|
139
|
+
# :check_boxes => :horizontal_radio_and_checkboxes,
|
140
|
+
# :radio_buttons => :horizontal_radio_and_checkboxes
|
146
141
|
# }
|
147
142
|
# }
|
148
143
|
|
@@ -169,28 +164,45 @@ EffectiveOrders.setup do |config|
|
|
169
164
|
send_order_receipt_to_seller: true, # Only applies to StripeConnect
|
170
165
|
send_payment_request_to_buyer: true,
|
171
166
|
send_pending_order_invoice_to_buyer: true,
|
172
|
-
|
167
|
+
send_order_receipts_when_mark_as_paid: false,
|
168
|
+
|
169
|
+
send_subscription_payment_succeeded: true,
|
170
|
+
send_subscription_payment_failed: true,
|
171
|
+
send_subscription_canceled: true,
|
172
|
+
send_subscription_trial_expiring: true, # Only if you schedule the rake task to run
|
173
|
+
send_subscription_trial_expired: true, # Only if you schedule the rake task to run
|
173
174
|
|
174
175
|
subject_prefix: '[example]',
|
176
|
+
|
175
177
|
subject_for_order_receipt_to_admin: '',
|
176
178
|
subject_for_order_receipt_to_buyer: '',
|
177
179
|
subject_for_order_receipt_to_seller: '',
|
178
180
|
subject_for_pending_order_invoice_to_buyer: '',
|
179
181
|
subject_for_payment_request_to_buyer: '',
|
180
182
|
|
183
|
+
subject_for_subscription_payment_succeeded: '',
|
184
|
+
subject_for_subscription_payment_failed: '',
|
185
|
+
subject_for_subscription_canceled: '',
|
186
|
+
subject_for_subscription_trial_expiring: '',
|
187
|
+
subject_for_subscription_trial_expired: '',
|
188
|
+
|
181
189
|
layout: 'effective_orders_mailer_layout',
|
182
190
|
|
183
191
|
default_from: 'info@example.com',
|
184
192
|
admin_email: 'admin@example.com',
|
185
193
|
|
186
194
|
deliver_method: nil, # :deliver (rails < 4.2), :deliver_now (rails >= 4.2) or :deliver_later
|
187
|
-
delayed_job_deliver: false
|
195
|
+
delayed_job_deliver: false # Use the oldschool pre-ActiveJob delayed_job way of sending email
|
188
196
|
}
|
189
197
|
|
190
198
|
#######################################
|
191
199
|
### Payment Provider specific options
|
192
200
|
#######################################
|
193
201
|
|
202
|
+
# Mark an order as paid without going through a processor
|
203
|
+
# This is accessed via the admin screens only. Must have can?(:admin, :effective_orders)
|
204
|
+
config.mark_as_paid_enabled = false
|
205
|
+
|
194
206
|
# Moneris configuration
|
195
207
|
config.moneris_enabled = false
|
196
208
|
|
@@ -239,10 +251,19 @@ EffectiveOrders.setup do |config|
|
|
239
251
|
|
240
252
|
# Stripe configuration
|
241
253
|
config.stripe_enabled = false
|
242
|
-
config.
|
254
|
+
config.subscriptions_enabled = false # https://stripe.com/docs/subscriptions
|
255
|
+
|
243
256
|
config.stripe_connect_enabled = false # https://stripe.com/docs/connect
|
244
257
|
config.stripe_connect_application_fee_method = Proc.new { |order_item| order_item.total * 0.10 } # 10 percent
|
245
258
|
|
259
|
+
config.subscription = {
|
260
|
+
trial_name: 'Free Trial',
|
261
|
+
trial_description: '45-Day Free Trial',
|
262
|
+
trial_period: 45.days,
|
263
|
+
trial_remind_at: [1.day, 3.days, 7.days], # Send email notification to trialing users 1, 3 and 7 days before expiring. false to disable.
|
264
|
+
webhook_secret: 'whsec_1234567890'
|
265
|
+
}
|
266
|
+
|
246
267
|
if Rails.env.production?
|
247
268
|
config.stripe = {
|
248
269
|
secret_key: '',
|
data/config/routes.rb
CHANGED
@@ -7,71 +7,71 @@ end
|
|
7
7
|
EffectiveOrders::Engine.routes.draw do
|
8
8
|
scope module: 'effective' do
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
match 'orders/moneris_postback', to: 'orders#moneris_postback', as: 'moneris_postback', via: :post
|
25
|
-
end
|
26
|
-
|
27
|
-
if EffectiveOrders.stripe_enabled
|
28
|
-
match 'orders/stripe_charge', to: 'orders#stripe_charge', as: 'stripe_charges', via: :post
|
29
|
-
end
|
10
|
+
resources :orders, except: [:destroy] do
|
11
|
+
member do
|
12
|
+
get :purchased
|
13
|
+
get :declined
|
14
|
+
get :send_buyer_receipt
|
15
|
+
|
16
|
+
post :app_checkout if EffectiveOrders.app_checkout_enabled
|
17
|
+
post :free if EffectiveOrders.allow_free_orders
|
18
|
+
post :mark_as_paid if EffectiveOrders.mark_as_paid_enabled
|
19
|
+
post :pay_by_cheque if EffectiveOrders.cheque_enabled
|
20
|
+
post :pretend if EffectiveOrders.allow_pretend_purchase_in_production && Rails.env.production?
|
21
|
+
post :pretend if EffectiveOrders.allow_pretend_purchase_in_development && !Rails.env.production?
|
22
|
+
post :refund if EffectiveOrders.allow_refunds
|
23
|
+
end
|
30
24
|
|
31
|
-
|
32
|
-
|
33
|
-
|
25
|
+
collection do
|
26
|
+
get :my_purchases
|
27
|
+
post :bulk_send_buyer_receipt
|
34
28
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
29
|
+
if EffectiveOrders.stripe_connect_enabled
|
30
|
+
get :stripe_connect_redirect_uri # oAuth2
|
31
|
+
get :my_sales
|
32
|
+
end
|
39
33
|
|
40
|
-
|
41
|
-
|
34
|
+
post :ccbill_postback if EffectiveOrders.ccbill_enabled
|
35
|
+
post :moneris_postback if EffectiveOrders.moneris_enabled
|
36
|
+
post :paypal_postback if EffectiveOrders.paypal_enabled
|
37
|
+
post :stripe_charge if EffectiveOrders.stripe_enabled
|
38
|
+
end
|
42
39
|
end
|
43
40
|
|
44
|
-
|
45
|
-
match 'orders/:id/app_checkout', to: 'orders#app_checkout', as: 'app_checkout', via: :post
|
46
|
-
end
|
41
|
+
post 'orders/:id', to: 'orders#update'
|
47
42
|
|
48
|
-
if
|
49
|
-
match '
|
43
|
+
if EffectiveOrders.subscriptions_enabled
|
44
|
+
match 'customer/settings', to: 'customers#edit', as: :customer_settings, via: [:get]
|
45
|
+
match 'customer/settings', to: 'customers#update', via: [:patch, :put]
|
46
|
+
match 'webhooks/stripe', to: 'webhooks#stripe', via: [:post, :put]
|
50
47
|
end
|
51
48
|
|
52
|
-
resources :orders, except: [:destroy]
|
53
|
-
|
54
49
|
match 'cart', to: 'carts#show', as: 'cart', via: :get
|
55
50
|
match 'cart', to: 'carts#destroy', via: :delete
|
56
51
|
|
57
52
|
# If you Tweak this route, please update EffectiveOrdersHelper too
|
58
53
|
match 'cart/:purchasable_type/:purchasable_id', to: 'carts#add_to_cart', via: [:get, :post], as: 'add_to_cart'
|
59
54
|
match 'cart/:id', to: 'carts#remove_from_cart', via: [:delete], as: 'remove_from_cart'
|
60
|
-
|
61
|
-
match 'webhooks/stripe', to: 'webhooks#stripe', via: [:post, :put]
|
62
55
|
end
|
63
56
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
post :send_payment_request
|
72
|
-
end
|
57
|
+
namespace :admin do
|
58
|
+
resources :customers, only: [:index, :show]
|
59
|
+
resources :orders do
|
60
|
+
member do
|
61
|
+
post :send_payment_request
|
62
|
+
post :checkout
|
63
|
+
patch :checkout
|
73
64
|
end
|
74
|
-
|
65
|
+
|
66
|
+
collection do
|
67
|
+
post :bulk_send_payment_request
|
68
|
+
end
|
69
|
+
|
75
70
|
end
|
71
|
+
|
72
|
+
post 'orders/:id', to: 'orders#update'
|
73
|
+
|
74
|
+
resources :order_items, only: [:index]
|
76
75
|
end
|
76
|
+
|
77
77
|
end
|
@@ -47,6 +47,7 @@ class CreateEffectiveOrders < ActiveRecord::Migration[4.2]
|
|
47
47
|
|
48
48
|
create_table <%= @carts_table_name %> do |t|
|
49
49
|
t.integer :user_id
|
50
|
+
t.integer :cart_items_count, :default => 0
|
50
51
|
t.timestamps
|
51
52
|
end
|
52
53
|
|
@@ -57,6 +58,7 @@ class CreateEffectiveOrders < ActiveRecord::Migration[4.2]
|
|
57
58
|
t.string :purchasable_type
|
58
59
|
t.integer :purchasable_id
|
59
60
|
|
61
|
+
t.string :unique
|
60
62
|
t.integer :quantity
|
61
63
|
|
62
64
|
t.timestamps
|
@@ -68,10 +70,17 @@ class CreateEffectiveOrders < ActiveRecord::Migration[4.2]
|
|
68
70
|
|
69
71
|
create_table <%= @customers_table_name %> do |t|
|
70
72
|
t.integer :user_id
|
73
|
+
|
71
74
|
t.string :stripe_customer_id
|
72
|
-
t.string :
|
75
|
+
t.string :active_card
|
76
|
+
|
77
|
+
t.string :stripe_subscription_id
|
78
|
+
t.string :status
|
79
|
+
|
73
80
|
t.string :stripe_connect_access_token
|
74
81
|
|
82
|
+
t.integer :subscriptions_count, :default => 0
|
83
|
+
|
75
84
|
t.timestamps
|
76
85
|
end
|
77
86
|
|
@@ -79,17 +88,22 @@ class CreateEffectiveOrders < ActiveRecord::Migration[4.2]
|
|
79
88
|
|
80
89
|
create_table <%= @subscriptions_table_name %> do |t|
|
81
90
|
t.integer :customer_id
|
91
|
+
|
92
|
+
t.integer :subscribable_id
|
93
|
+
t.string :subscribable_type
|
94
|
+
|
82
95
|
t.string :stripe_plan_id
|
83
|
-
t.string :
|
84
|
-
|
85
|
-
t.string :
|
96
|
+
t.string :status
|
97
|
+
|
98
|
+
t.string :name
|
86
99
|
t.integer :price, :default => 0
|
87
100
|
|
88
101
|
t.timestamps
|
89
102
|
end
|
90
103
|
|
91
104
|
add_index <%= @subscriptions_table_name %>, :customer_id
|
92
|
-
add_index <%= @subscriptions_table_name %>, :
|
105
|
+
add_index <%= @subscriptions_table_name %>, :subscribable_id
|
106
|
+
add_index <%= @subscriptions_table_name %>, [:subscribable_type, :subscribable_id]
|
93
107
|
|
94
108
|
create_table <%= @products_table_name %> do |t|
|
95
109
|
t.string :title
|
data/lib/effective_orders.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'simple_form'
|
2
1
|
require 'effective_addresses'
|
3
2
|
require 'effective_orders/engine'
|
4
3
|
require 'effective_orders/version'
|
@@ -10,6 +9,8 @@ module EffectiveOrders
|
|
10
9
|
DECLINED = 'declined'
|
11
10
|
PENDING = 'pending'
|
12
11
|
|
12
|
+
PURCHASE_STATES = { nil => ABANDONED, PURCHASED => PURCHASED, DECLINED => DECLINED, PENDING => PENDING }
|
13
|
+
|
13
14
|
# The following are all valid config keys
|
14
15
|
mattr_accessor :orders_table_name
|
15
16
|
mattr_accessor :order_items_table_name
|
@@ -29,12 +30,9 @@ module EffectiveOrders
|
|
29
30
|
mattr_accessor :layout
|
30
31
|
mattr_accessor :simple_form_options
|
31
32
|
mattr_accessor :admin_simple_form_options
|
32
|
-
|
33
|
-
mattr_accessor :use_active_admin
|
34
|
-
mattr_accessor :active_admin_namespace
|
33
|
+
mattr_accessor :show_order_history_button
|
35
34
|
|
36
35
|
mattr_accessor :obfuscate_order_ids
|
37
|
-
mattr_accessor :silence_deprecation_warnings
|
38
36
|
|
39
37
|
mattr_accessor :allow_pretend_purchase_in_development
|
40
38
|
mattr_accessor :allow_pretend_purchase_in_production
|
@@ -56,73 +54,63 @@ module EffectiveOrders
|
|
56
54
|
|
57
55
|
mattr_accessor :minimum_charge
|
58
56
|
mattr_accessor :allow_free_orders
|
59
|
-
mattr_accessor :
|
57
|
+
mattr_accessor :allow_refunds
|
60
58
|
|
59
|
+
mattr_accessor :app_checkout_enabled
|
60
|
+
mattr_accessor :ccbill_enabled
|
61
61
|
mattr_accessor :cheque_enabled
|
62
|
-
mattr_accessor :
|
62
|
+
mattr_accessor :mark_as_paid_enabled
|
63
63
|
mattr_accessor :moneris_enabled
|
64
|
-
mattr_accessor :
|
65
|
-
mattr_accessor :app_checkout_enabled
|
64
|
+
mattr_accessor :paypal_enabled
|
66
65
|
|
67
66
|
mattr_accessor :stripe_enabled
|
68
|
-
mattr_accessor :stripe_subscriptions_enabled
|
69
67
|
mattr_accessor :stripe_connect_enabled
|
70
68
|
|
69
|
+
mattr_accessor :subscriptions_enabled
|
70
|
+
|
71
71
|
# application fee is required if stripe_connect_enabled is true
|
72
72
|
mattr_accessor :stripe_connect_application_fee_method
|
73
73
|
|
74
74
|
# These are hashes of configs
|
75
|
+
mattr_accessor :app_checkout
|
76
|
+
mattr_accessor :ccbill
|
77
|
+
mattr_accessor :cheque
|
75
78
|
mattr_accessor :mailer
|
76
|
-
mattr_accessor :paypal
|
77
79
|
mattr_accessor :moneris
|
80
|
+
mattr_accessor :paypal
|
78
81
|
mattr_accessor :stripe
|
79
|
-
mattr_accessor :
|
80
|
-
mattr_accessor :app_checkout
|
81
|
-
mattr_accessor :cheque
|
82
|
+
mattr_accessor :subscription
|
82
83
|
|
83
84
|
mattr_accessor :deliver_method
|
84
85
|
|
85
86
|
def self.setup
|
86
87
|
yield self
|
87
|
-
|
88
|
-
if EffectiveOrders.stripe_enabled
|
89
|
-
begin
|
90
|
-
require 'stripe'
|
91
|
-
rescue Exception
|
92
|
-
raise "unable to load stripe. Plese add gem 'stripe' to your Gemfile and then 'bundle install'"
|
93
|
-
end
|
94
|
-
|
95
|
-
::Stripe.api_key = stripe[:secret_key]
|
96
|
-
end
|
97
88
|
end
|
98
89
|
|
99
90
|
def self.authorized?(controller, action, resource)
|
100
|
-
if
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
end
|
91
|
+
@_exceptions ||= [Effective::AccessDenied, (CanCan::AccessDenied if defined?(CanCan)), (Pundit::NotAuthorizedError if defined?(Pundit))].compact
|
92
|
+
|
93
|
+
return !!authorization_method unless authorization_method.respond_to?(:call)
|
94
|
+
controller = controller.controller if controller.respond_to?(:controller)
|
105
95
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
ActiveSupport::Deprecation.warn('EffectiveOrders.minimum_charge config option is a non-integer. It should be an Integer representing the number of cents. Continuing with (price * 100.0).round(0).to_i conversion') unless EffectiveOrders.silence_deprecation_warnings
|
111
|
-
((@@minimum_charge * 100.0).round(0).to_i rescue nil)
|
96
|
+
begin
|
97
|
+
!!(controller || self).instance_exec((controller || self), action, resource, &authorization_method)
|
98
|
+
rescue *@_exceptions
|
99
|
+
false
|
112
100
|
end
|
113
101
|
end
|
114
102
|
|
115
|
-
def self.
|
116
|
-
|
103
|
+
def self.authorize!(controller, action, resource)
|
104
|
+
raise Effective::AccessDenied unless authorized?(controller, action, resource)
|
117
105
|
end
|
118
106
|
|
119
107
|
def self.permitted_params
|
120
108
|
[
|
121
|
-
:note, :
|
109
|
+
:note, :terms_and_conditions,
|
122
110
|
billing_address: EffectiveAddresses.permitted_params,
|
123
111
|
shipping_address: EffectiveAddresses.permitted_params,
|
124
112
|
user_attributes: (EffectiveOrders.collect_user_fields || []),
|
125
|
-
|
113
|
+
subscripter: [:stripe_plan_id, :stripe_token]
|
126
114
|
]
|
127
115
|
end
|
128
116
|
|
@@ -152,15 +140,63 @@ module EffectiveOrders
|
|
152
140
|
].compact
|
153
141
|
end
|
154
142
|
|
143
|
+
# One of these is used when Admin marks as paid
|
155
144
|
def self.other_payment_providers
|
156
145
|
['credit card', 'none', 'other']
|
157
146
|
end
|
158
147
|
|
159
|
-
def self.
|
160
|
-
|
148
|
+
def self.can_skip_checkout_step1?
|
149
|
+
return false if require_billing_address
|
150
|
+
return false if require_shipping_address
|
151
|
+
return false if collect_note
|
152
|
+
return false if terms_and_conditions
|
153
|
+
return false if collect_user_fields.present?
|
154
|
+
|
155
|
+
true
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.stripe_plans
|
159
|
+
return {} unless (stripe_enabled && subscriptions_enabled)
|
160
|
+
|
161
|
+
@stripe_plans ||= (
|
162
|
+
plans = Stripe::Plan.all.inject({}) do |h, plan|
|
163
|
+
occurrence = case plan.interval
|
164
|
+
when 'daily' ; '/day'
|
165
|
+
when 'weekly' ; '/week'
|
166
|
+
when 'monthly' ; '/month'
|
167
|
+
when 'yearly' ; '/year'
|
168
|
+
when 'day' ; plan.interval_count == 1 ? '/day' : " every #{plan.interval_count} days"
|
169
|
+
when 'week' ; plan.interval_count == 1 ? '/week' : " every #{plan.interval_count} weeks"
|
170
|
+
when 'month' ; plan.interval_count == 1 ? '/month' : " every #{plan.interval_count} months"
|
171
|
+
when 'year' ; plan.interval_count == 1 ? '/year' : " every #{plan.interval_count} years"
|
172
|
+
else ; plan.interval
|
173
|
+
end
|
174
|
+
|
175
|
+
h[plan.id] = {
|
176
|
+
id: plan.id,
|
177
|
+
name: plan.name,
|
178
|
+
amount: plan.amount,
|
179
|
+
currency: plan.currency,
|
180
|
+
description: "$#{'%0.2f' % (plan.amount / 100.0)} #{plan.currency.upcase}#{occurrence}",
|
181
|
+
occurrence: "#{occurrence}",
|
182
|
+
interval: plan.interval,
|
183
|
+
interval_count: plan.interval_count
|
184
|
+
}; h
|
185
|
+
end
|
186
|
+
|
187
|
+
if subscription.kind_of?(Hash)
|
188
|
+
plans['trial'] = {
|
189
|
+
id: 'trial',
|
190
|
+
amount: 0,
|
191
|
+
name: (subscription[:trial_name] || 'Free Trial'),
|
192
|
+
description: (subscription[:trial_description] || 'Free Trial')
|
193
|
+
}
|
194
|
+
end
|
195
|
+
|
196
|
+
plans
|
197
|
+
)
|
161
198
|
end
|
162
199
|
|
163
200
|
class SoldOutException < Exception; end
|
164
201
|
class AlreadyPurchasedException < Exception; end
|
165
|
-
|
166
202
|
end
|