effective_orders 4.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +1004 -0
- data/app/assets/images/effective_orders/stripe.png +0 -0
- data/app/assets/javascripts/effective_orders.js +6 -0
- data/app/assets/javascripts/effective_orders/customers.js.coffee +32 -0
- data/app/assets/javascripts/effective_orders/providers/stripe.js.coffee +77 -0
- data/app/assets/javascripts/effective_orders/subscriptions.js.coffee +81 -0
- data/app/assets/stylesheets/effective_orders.scss +2 -0
- data/app/assets/stylesheets/effective_orders/_cart.scss +4 -0
- data/app/assets/stylesheets/effective_orders/_order.scss +58 -0
- data/app/controllers/admin/customers_controller.rb +24 -0
- data/app/controllers/admin/order_items_controller.rb +16 -0
- data/app/controllers/admin/orders_controller.rb +223 -0
- data/app/controllers/effective/carts_controller.rb +85 -0
- data/app/controllers/effective/concerns/purchase.rb +62 -0
- data/app/controllers/effective/customers_controller.rb +20 -0
- data/app/controllers/effective/orders_controller.rb +162 -0
- data/app/controllers/effective/providers/cheque.rb +22 -0
- 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 +60 -0
- data/app/controllers/effective/providers/paypal.rb +33 -0
- data/app/controllers/effective/providers/phone.rb +22 -0
- data/app/controllers/effective/providers/pretend.rb +26 -0
- data/app/controllers/effective/providers/refund.rb +33 -0
- data/app/controllers/effective/providers/stripe.rb +72 -0
- data/app/controllers/effective/subscripter_controller.rb +18 -0
- data/app/controllers/effective/webhooks_controller.rb +109 -0
- data/app/datatables/admin/effective_customers_datatable.rb +22 -0
- data/app/datatables/admin/effective_orders_datatable.rb +100 -0
- data/app/datatables/effective_orders_datatable.rb +79 -0
- data/app/helpers/effective_carts_helper.rb +113 -0
- data/app/helpers/effective_orders_helper.rb +143 -0
- data/app/helpers/effective_paypal_helper.rb +49 -0
- data/app/helpers/effective_stripe_helper.rb +85 -0
- data/app/helpers/effective_subscriptions_helper.rb +34 -0
- data/app/mailers/effective/orders_mailer.rb +196 -0
- data/app/models/concerns/acts_as_purchasable.rb +118 -0
- data/app/models/concerns/acts_as_subscribable.rb +90 -0
- data/app/models/concerns/acts_as_subscribable_buyer.rb +49 -0
- data/app/models/effective/access_denied.rb +17 -0
- data/app/models/effective/cart.rb +88 -0
- data/app/models/effective/cart_item.rb +40 -0
- data/app/models/effective/customer.rb +92 -0
- data/app/models/effective/order.rb +541 -0
- data/app/models/effective/order_item.rb +63 -0
- data/app/models/effective/product.rb +23 -0
- data/app/models/effective/sold_out_validator.rb +7 -0
- data/app/models/effective/subscripter.rb +185 -0
- data/app/models/effective/subscription.rb +95 -0
- data/app/models/effective/tax_rate_calculator.rb +48 -0
- data/app/views/admin/customers/_actions.html.haml +2 -0
- data/app/views/admin/customers/index.html.haml +6 -0
- data/app/views/admin/customers/show.html.haml +6 -0
- data/app/views/admin/order_items/index.html.haml +3 -0
- data/app/views/admin/orders/_datatable_actions.html.haml +18 -0
- data/app/views/admin/orders/_form.html.haml +35 -0
- data/app/views/admin/orders/_form_note_internal.html.haml +7 -0
- data/app/views/admin/orders/_order_actions.html.haml +9 -0
- data/app/views/admin/orders/_order_item_fields.html.haml +14 -0
- data/app/views/admin/orders/checkout.html.haml +3 -0
- data/app/views/admin/orders/edit.html.haml +6 -0
- data/app/views/admin/orders/index.html.haml +6 -0
- data/app/views/admin/orders/new.html.haml +4 -0
- data/app/views/admin/orders/show.html.haml +4 -0
- data/app/views/effective/carts/_cart.html.haml +28 -0
- data/app/views/effective/carts/_cart_actions.html.haml +3 -0
- data/app/views/effective/carts/show.html.haml +17 -0
- data/app/views/effective/customers/_customer.html.haml +72 -0
- data/app/views/effective/customers/_form.html.haml +21 -0
- data/app/views/effective/customers/edit.html.haml +4 -0
- data/app/views/effective/customers/update.js.erb +5 -0
- data/app/views/effective/orders/_checkout_actions.html.haml +3 -0
- data/app/views/effective/orders/_checkout_step1.html.haml +4 -0
- data/app/views/effective/orders/_checkout_step2.html.haml +37 -0
- data/app/views/effective/orders/_datatable_actions.html.haml +2 -0
- data/app/views/effective/orders/_fields.html.haml +31 -0
- data/app/views/effective/orders/_fields_note.html.haml +7 -0
- data/app/views/effective/orders/_fields_terms.html.haml +8 -0
- data/app/views/effective/orders/_order.html.haml +11 -0
- data/app/views/effective/orders/_order_actions.html.haml +18 -0
- data/app/views/effective/orders/_order_deferred.html.haml +9 -0
- data/app/views/effective/orders/_order_footer.html.haml +1 -0
- data/app/views/effective/orders/_order_header.html.haml +23 -0
- data/app/views/effective/orders/_order_items.html.haml +72 -0
- data/app/views/effective/orders/_order_notes.html.haml +17 -0
- data/app/views/effective/orders/_order_payment.html.haml +24 -0
- data/app/views/effective/orders/_order_shipping.html.haml +30 -0
- data/app/views/effective/orders/_orders_table.html.haml +23 -0
- data/app/views/effective/orders/cheque/_form.html.haml +4 -0
- data/app/views/effective/orders/declined.html.haml +12 -0
- data/app/views/effective/orders/deferred.html.haml +13 -0
- data/app/views/effective/orders/deferred/_form.html.haml +16 -0
- data/app/views/effective/orders/edit.html.haml +3 -0
- data/app/views/effective/orders/free/_form.html.haml +5 -0
- data/app/views/effective/orders/index.html.haml +3 -0
- data/app/views/effective/orders/mark_as_paid/_form.html.haml +23 -0
- data/app/views/effective/orders/moneris/_form.html.haml +47 -0
- data/app/views/effective/orders/new.html.haml +3 -0
- data/app/views/effective/orders/paypal/_form.html.haml +5 -0
- data/app/views/effective/orders/phone/_form.html.haml +4 -0
- data/app/views/effective/orders/pretend/_form.html.haml +8 -0
- data/app/views/effective/orders/purchased.html.haml +11 -0
- data/app/views/effective/orders/refund/_form.html.haml +5 -0
- data/app/views/effective/orders/show.html.haml +6 -0
- data/app/views/effective/orders/stripe/_element.html.haml +8 -0
- data/app/views/effective/orders/stripe/_form.html.haml +31 -0
- data/app/views/effective/orders_mailer/order_error.html.haml +11 -0
- data/app/views/effective/orders_mailer/order_receipt_to_admin.html.haml +2 -0
- data/app/views/effective/orders_mailer/order_receipt_to_buyer.html.haml +2 -0
- data/app/views/effective/orders_mailer/payment_request_to_buyer.html.haml +13 -0
- data/app/views/effective/orders_mailer/pending_order_invoice_to_buyer.html.haml +13 -0
- data/app/views/effective/orders_mailer/refund_notification_to_admin.html.haml +15 -0
- data/app/views/effective/orders_mailer/subscription_canceled.html.haml +9 -0
- data/app/views/effective/orders_mailer/subscription_created.html.haml +13 -0
- data/app/views/effective/orders_mailer/subscription_event_to_admin.html.haml +13 -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_trialing.html.haml +7 -0
- data/app/views/effective/orders_mailer/subscription_updated.html.haml +13 -0
- data/app/views/effective/subscripter/_form.html.haml +60 -0
- data/app/views/effective/subscripter/_plan.html.haml +23 -0
- data/app/views/layouts/effective_orders_mailer_layout.html.haml +25 -0
- data/config/effective_orders.rb +279 -0
- data/config/routes.rb +70 -0
- data/db/migrate/01_create_effective_orders.rb.erb +137 -0
- data/lib/effective_orders.rb +243 -0
- data/lib/effective_orders/engine.rb +60 -0
- data/lib/effective_orders/version.rb +3 -0
- data/lib/generators/effective_orders/install_generator.rb +63 -0
- data/lib/generators/templates/effective_orders_mailer_preview.rb +120 -0
- data/lib/tasks/effective_orders_tasks.rake +69 -0
- metadata +276 -0
data/config/routes.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
EffectiveOrders::Engine.routes.draw do
|
2
|
+
scope :module => 'effective' do
|
3
|
+
resources :orders, except: [:destroy] do
|
4
|
+
member do
|
5
|
+
get :purchased
|
6
|
+
get :deferred
|
7
|
+
get :declined
|
8
|
+
get :send_buyer_receipt
|
9
|
+
|
10
|
+
post :free if EffectiveOrders.free?
|
11
|
+
post :mark_as_paid if EffectiveOrders.mark_as_paid?
|
12
|
+
post :cheque if EffectiveOrders.cheque?
|
13
|
+
post :phone if EffectiveOrders.phone?
|
14
|
+
post :pretend if EffectiveOrders.pretend?
|
15
|
+
post :refund if EffectiveOrders.refund?
|
16
|
+
post :stripe if EffectiveOrders.stripe?
|
17
|
+
end
|
18
|
+
|
19
|
+
collection do
|
20
|
+
post :bulk_send_buyer_receipt
|
21
|
+
|
22
|
+
post :moneris_postback if EffectiveOrders.moneris?
|
23
|
+
post :paypal_postback if EffectiveOrders.paypal?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
post 'orders/:id', to: 'orders#update'
|
28
|
+
|
29
|
+
if EffectiveOrders.subscriptions?
|
30
|
+
match 'subscribe', to: 'subscripter#update', via: :post, as: :subscripter
|
31
|
+
|
32
|
+
match 'customer/settings', to: 'customers#edit', as: :customer_settings, via: [:get]
|
33
|
+
match 'customer/settings', to: 'customers#update', via: [:patch, :put, :post]
|
34
|
+
match 'webhooks/stripe', to: 'webhooks#stripe', via: [:get, :post, :put]
|
35
|
+
end
|
36
|
+
|
37
|
+
match 'cart', to: 'carts#show', as: 'cart', via: :get
|
38
|
+
match 'cart', to: 'carts#destroy', via: :delete
|
39
|
+
|
40
|
+
# If you Tweak this route, please update EffectiveOrdersHelper too
|
41
|
+
match 'cart/:purchasable_type/:purchasable_id', to: 'carts#add_to_cart', via: [:get, :post], as: 'add_to_cart'
|
42
|
+
match 'cart/:id', to: 'carts#remove_from_cart', via: [:delete], as: 'remove_from_cart'
|
43
|
+
end
|
44
|
+
|
45
|
+
namespace :admin do
|
46
|
+
resources :customers, only: [:index, :show]
|
47
|
+
|
48
|
+
resources :orders do
|
49
|
+
member do
|
50
|
+
post :send_payment_request
|
51
|
+
|
52
|
+
get :checkout
|
53
|
+
post :checkout
|
54
|
+
patch :checkout
|
55
|
+
end
|
56
|
+
|
57
|
+
collection do
|
58
|
+
post :bulk_send_payment_request
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
post 'orders/:id', to: 'orders#update'
|
63
|
+
|
64
|
+
resources :order_items, only: [:index]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
Rails.application.routes.draw do
|
69
|
+
mount EffectiveOrders::Engine => '/', as: 'effective_orders'
|
70
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
class CreateEffectiveOrders < ActiveRecord::Migration[4.2]
|
2
|
+
def self.up
|
3
|
+
create_table <%= @orders_table_name %> do |t|
|
4
|
+
t.integer :user_id
|
5
|
+
|
6
|
+
t.integer :parent_id
|
7
|
+
t.string :parent_type
|
8
|
+
|
9
|
+
t.string :state
|
10
|
+
t.datetime :purchased_at
|
11
|
+
|
12
|
+
t.text :note
|
13
|
+
t.text :note_to_buyer
|
14
|
+
t.text :note_internal
|
15
|
+
|
16
|
+
t.string :billing_name
|
17
|
+
t.string :email
|
18
|
+
t.string :cc
|
19
|
+
|
20
|
+
t.text :payment
|
21
|
+
t.string :payment_provider
|
22
|
+
t.string :payment_card
|
23
|
+
|
24
|
+
t.decimal :tax_rate, :precision => 6, :scale => 3
|
25
|
+
|
26
|
+
t.integer :subtotal
|
27
|
+
t.integer :tax
|
28
|
+
t.integer :total
|
29
|
+
|
30
|
+
t.timestamps
|
31
|
+
end
|
32
|
+
|
33
|
+
add_index <%= @orders_table_name %>, :user_id
|
34
|
+
|
35
|
+
|
36
|
+
create_table <%= @order_items_table_name %> do |t|
|
37
|
+
t.integer :order_id
|
38
|
+
t.string :purchasable_type
|
39
|
+
t.integer :purchasable_id
|
40
|
+
|
41
|
+
t.string :name
|
42
|
+
t.integer :quantity
|
43
|
+
t.integer :price, :default => 0
|
44
|
+
t.boolean :tax_exempt
|
45
|
+
|
46
|
+
t.timestamps
|
47
|
+
end
|
48
|
+
|
49
|
+
add_index <%= @order_items_table_name %>, :order_id
|
50
|
+
add_index <%= @order_items_table_name %>, :purchasable_id
|
51
|
+
add_index <%= @order_items_table_name %>, [:purchasable_type, :purchasable_id]
|
52
|
+
|
53
|
+
|
54
|
+
create_table <%= @carts_table_name %> do |t|
|
55
|
+
t.integer :user_id
|
56
|
+
t.integer :cart_items_count, :default => 0
|
57
|
+
t.timestamps
|
58
|
+
end
|
59
|
+
|
60
|
+
add_index <%= @carts_table_name %>, :user_id
|
61
|
+
|
62
|
+
create_table <%= @cart_items_table_name %> do |t|
|
63
|
+
t.integer :cart_id
|
64
|
+
t.string :purchasable_type
|
65
|
+
t.integer :purchasable_id
|
66
|
+
|
67
|
+
t.string :unique
|
68
|
+
t.integer :quantity
|
69
|
+
|
70
|
+
t.timestamps
|
71
|
+
end
|
72
|
+
|
73
|
+
add_index <%= @cart_items_table_name %>, :cart_id
|
74
|
+
add_index <%= @cart_items_table_name %>, :purchasable_id
|
75
|
+
add_index <%= @cart_items_table_name %>, [:purchasable_type, :purchasable_id]
|
76
|
+
|
77
|
+
create_table <%= @customers_table_name %> do |t|
|
78
|
+
t.integer :user_id
|
79
|
+
|
80
|
+
t.string :stripe_customer_id
|
81
|
+
t.string :payment_method_id
|
82
|
+
t.string :active_card
|
83
|
+
t.string :status
|
84
|
+
|
85
|
+
t.integer :subscriptions_count, :default => 0
|
86
|
+
|
87
|
+
t.timestamps
|
88
|
+
end
|
89
|
+
|
90
|
+
add_index <%= @customers_table_name %>, :user_id
|
91
|
+
|
92
|
+
create_table <%= @subscriptions_table_name %> do |t|
|
93
|
+
t.integer :customer_id
|
94
|
+
|
95
|
+
t.integer :subscribable_id
|
96
|
+
t.string :subscribable_type
|
97
|
+
|
98
|
+
t.string :stripe_plan_id
|
99
|
+
t.string :stripe_subscription_id
|
100
|
+
|
101
|
+
t.string :name
|
102
|
+
t.string :description
|
103
|
+
t.string :interval
|
104
|
+
t.integer :quantity
|
105
|
+
t.string :status
|
106
|
+
|
107
|
+
t.timestamps
|
108
|
+
end
|
109
|
+
|
110
|
+
add_index <%= @subscriptions_table_name %>, :customer_id
|
111
|
+
add_index <%= @subscriptions_table_name %>, :subscribable_id
|
112
|
+
add_index <%= @subscriptions_table_name %>, [:subscribable_type, :subscribable_id]
|
113
|
+
|
114
|
+
create_table <%= @products_table_name %> do |t|
|
115
|
+
t.integer :purchased_order_id
|
116
|
+
|
117
|
+
t.string :name
|
118
|
+
t.integer :price
|
119
|
+
t.boolean :tax_exempt, :default => false
|
120
|
+
|
121
|
+
t.string :qb_item_name
|
122
|
+
|
123
|
+
t.timestamps
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.down
|
129
|
+
drop_table <%= @orders_table_name %>
|
130
|
+
drop_table <%= @order_items_table_name %>
|
131
|
+
drop_table <%= @carts_table_name %>
|
132
|
+
drop_table <%= @cart_items_table_name %>
|
133
|
+
drop_table <%= @customers_table_name %>
|
134
|
+
drop_table <%= @subscriptions_table_name %>
|
135
|
+
drop_table <%= @products_table_name %>
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,243 @@
|
|
1
|
+
require 'effective_addresses'
|
2
|
+
require 'effective_orders/engine'
|
3
|
+
require 'effective_orders/version'
|
4
|
+
|
5
|
+
module EffectiveOrders
|
6
|
+
PENDING = 'pending'.freeze # New orders are created in a pending state
|
7
|
+
CONFIRMED = 'confirmed'.freeze # Once the order has passed checkout step 1
|
8
|
+
DEFERRED = 'deferred'.freeze # Deferred providers. Cheque or Phone was selected.
|
9
|
+
PURCHASED = 'purchased'.freeze # Purchased by provider
|
10
|
+
DECLINED = 'declined'.freeze # Declined by provider
|
11
|
+
|
12
|
+
STATES = { PENDING => PENDING, CONFIRMED => CONFIRMED, DEFERRED => DEFERRED, PURCHASED => PURCHASED, DECLINED => DECLINED }
|
13
|
+
|
14
|
+
# Subscription statuses (as per stripe)
|
15
|
+
ACTIVE = 'active'.freeze
|
16
|
+
PAST_DUE = 'past_due'.freeze
|
17
|
+
CANCELED = 'canceled'.freeze
|
18
|
+
|
19
|
+
STATUSES = { ACTIVE => ACTIVE, PAST_DUE => PAST_DUE, CANCELED => CANCELED }
|
20
|
+
|
21
|
+
# The following are all valid config keys
|
22
|
+
mattr_accessor :orders_table_name
|
23
|
+
mattr_accessor :order_items_table_name
|
24
|
+
mattr_accessor :carts_table_name
|
25
|
+
mattr_accessor :cart_items_table_name
|
26
|
+
mattr_accessor :customers_table_name
|
27
|
+
mattr_accessor :subscriptions_table_name
|
28
|
+
mattr_accessor :products_table_name
|
29
|
+
|
30
|
+
mattr_accessor :authorization_method
|
31
|
+
|
32
|
+
mattr_accessor :layout
|
33
|
+
mattr_accessor :mailer
|
34
|
+
|
35
|
+
mattr_accessor :orders_collection_scope
|
36
|
+
mattr_accessor :order_tax_rate_method
|
37
|
+
|
38
|
+
mattr_accessor :obfuscate_order_ids
|
39
|
+
mattr_accessor :billing_address
|
40
|
+
mattr_accessor :shipping_address
|
41
|
+
mattr_accessor :use_address_full_name
|
42
|
+
|
43
|
+
mattr_accessor :collect_note
|
44
|
+
mattr_accessor :collect_note_required
|
45
|
+
mattr_accessor :collect_note_message
|
46
|
+
|
47
|
+
mattr_accessor :terms_and_conditions
|
48
|
+
mattr_accessor :terms_and_conditions_label
|
49
|
+
|
50
|
+
mattr_accessor :minimum_charge
|
51
|
+
|
52
|
+
# Features
|
53
|
+
mattr_accessor :free_enabled
|
54
|
+
mattr_accessor :mark_as_paid_enabled
|
55
|
+
mattr_accessor :pretend_enabled
|
56
|
+
mattr_accessor :pretend_message
|
57
|
+
|
58
|
+
# Payment processors. false or Hash
|
59
|
+
mattr_accessor :cheque
|
60
|
+
mattr_accessor :moneris
|
61
|
+
mattr_accessor :paypal
|
62
|
+
mattr_accessor :phone
|
63
|
+
mattr_accessor :refund
|
64
|
+
mattr_accessor :stripe
|
65
|
+
mattr_accessor :subscriptions # Stripe subscriptions
|
66
|
+
mattr_accessor :trial # Trial mode
|
67
|
+
|
68
|
+
def self.setup
|
69
|
+
yield self
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.authorized?(controller, action, resource)
|
73
|
+
@_exceptions ||= [Effective::AccessDenied, (CanCan::AccessDenied if defined?(CanCan)), (Pundit::NotAuthorizedError if defined?(Pundit))].compact
|
74
|
+
|
75
|
+
return !!authorization_method unless authorization_method.respond_to?(:call)
|
76
|
+
controller = controller.controller if controller.respond_to?(:controller)
|
77
|
+
|
78
|
+
begin
|
79
|
+
!!(controller || self).instance_exec((controller || self), action, resource, &authorization_method)
|
80
|
+
rescue *@_exceptions
|
81
|
+
false
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.authorize!(controller, action, resource)
|
86
|
+
raise Effective::AccessDenied.new('Access Denied', action, resource) unless authorized?(controller, action, resource)
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.permitted_params
|
90
|
+
[
|
91
|
+
:cc, :note, :terms_and_conditions, :confirmed_checkout,
|
92
|
+
billing_address: EffectiveAddresses.permitted_params,
|
93
|
+
shipping_address: EffectiveAddresses.permitted_params,
|
94
|
+
subscripter: [:stripe_plan_id, :stripe_token]
|
95
|
+
]
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.cheque?
|
99
|
+
cheque.kind_of?(Hash)
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.free?
|
103
|
+
free_enabled == true
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.deferred?
|
107
|
+
deferred_providers.present?
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.mark_as_paid?
|
111
|
+
mark_as_paid_enabled == true
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.moneris?
|
115
|
+
moneris.kind_of?(Hash)
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.paypal?
|
119
|
+
paypal.kind_of?(Hash)
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.phone?
|
123
|
+
phone.kind_of?(Hash)
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.pretend?
|
127
|
+
pretend_enabled == true
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.refund?
|
131
|
+
refund.kind_of?(Hash)
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.stripe?
|
135
|
+
stripe.kind_of?(Hash)
|
136
|
+
end
|
137
|
+
|
138
|
+
def self.subscriptions?
|
139
|
+
subscriptions.kind_of?(Hash)
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.trial?
|
143
|
+
trial.kind_of?(Hash)
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.single_payment_processor?
|
147
|
+
[moneris?, paypal?, stripe?].select { |enabled| enabled }.length == 1
|
148
|
+
end
|
149
|
+
|
150
|
+
# The Effective::Order.payment_provider value must be in this collection
|
151
|
+
def self.payment_providers
|
152
|
+
[
|
153
|
+
('cheque' if cheque?),
|
154
|
+
('credit card' if mark_as_paid?),
|
155
|
+
('free' if free?),
|
156
|
+
('moneris' if moneris?),
|
157
|
+
('paypal' if paypal?),
|
158
|
+
('phone' if phone?),
|
159
|
+
('pretend' if pretend?),
|
160
|
+
('refund' if refund?),
|
161
|
+
('stripe' if stripe?),
|
162
|
+
('other' if mark_as_paid?),
|
163
|
+
'none'
|
164
|
+
].compact
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.deferred_providers
|
168
|
+
[('cheque' if cheque?), ('phone' if phone?)].compact
|
169
|
+
end
|
170
|
+
|
171
|
+
def self.can_skip_checkout_step1?
|
172
|
+
return false if require_billing_address
|
173
|
+
return false if require_shipping_address
|
174
|
+
return false if collect_note
|
175
|
+
return false if terms_and_conditions
|
176
|
+
true
|
177
|
+
end
|
178
|
+
|
179
|
+
def self.stripe_plans
|
180
|
+
return [] unless (stripe? && subscriptions?)
|
181
|
+
|
182
|
+
@stripe_plans ||= (
|
183
|
+
Rails.logger.info '[STRIPE] index plans'
|
184
|
+
|
185
|
+
plans = begin
|
186
|
+
Stripe::Plan.respond_to?(:all) ? Stripe::Plan.all : Stripe::Plan.list
|
187
|
+
rescue => e
|
188
|
+
raise e if Rails.env.production?
|
189
|
+
Rails.logger.info "[STRIPE ERROR]: #{e.message}"
|
190
|
+
Rails.logger.info "[STRIPE ERROR]: effective_orders continuing with empty stripe plans. This would fail loudly in Rails.env.production."
|
191
|
+
[]
|
192
|
+
end
|
193
|
+
|
194
|
+
plans = plans.map do |plan|
|
195
|
+
description = ("$#{'%0.2f' % (plan.amount / 100.0)}" + ' ' + plan.currency.upcase + '/' + plan.interval.to_s)
|
196
|
+
|
197
|
+
{
|
198
|
+
id: plan.id,
|
199
|
+
product_id: plan.product,
|
200
|
+
name: plan.nickname || description,
|
201
|
+
description: description,
|
202
|
+
amount: plan.amount,
|
203
|
+
currency: plan.currency,
|
204
|
+
interval: plan.interval,
|
205
|
+
interval_count: plan.interval_count,
|
206
|
+
trial_period_days: plan.trial_period_days
|
207
|
+
}
|
208
|
+
end.sort do |x, y|
|
209
|
+
val ||= (x[:interval] <=> y[:interval])
|
210
|
+
val = nil if val == 0
|
211
|
+
|
212
|
+
val ||= (x[:amount] <=> y[:amount])
|
213
|
+
val = nil if val == 0
|
214
|
+
|
215
|
+
val ||= (x[:name] <=> y[:name])
|
216
|
+
val = nil if val == 0
|
217
|
+
|
218
|
+
val || (x[:id] <=> y[:id])
|
219
|
+
end
|
220
|
+
|
221
|
+
# Calculate savings for any yearly per user plans, based on their matching monthly plans
|
222
|
+
plans.select { |plan| plan[:interval] == 'year' }.each do |yearly|
|
223
|
+
monthly_name = yearly[:name].downcase.gsub('year', 'month')
|
224
|
+
monthly = plans.find { |plan| plan[:interval] == 'month' && plan[:name].downcase == monthly_name }
|
225
|
+
next unless monthly
|
226
|
+
|
227
|
+
savings = (monthly[:amount].to_i * 12) - yearly[:amount].to_i
|
228
|
+
next unless savings > 0
|
229
|
+
|
230
|
+
yearly[:savings] = savings
|
231
|
+
end
|
232
|
+
|
233
|
+
plans
|
234
|
+
)
|
235
|
+
end
|
236
|
+
|
237
|
+
def self.stripe_plans_collection
|
238
|
+
stripe_plans.map { |plan| [plan[:name], plan[:id]] }
|
239
|
+
end
|
240
|
+
|
241
|
+
class SoldOutException < Exception; end
|
242
|
+
class AlreadyPurchasedException < Exception; end
|
243
|
+
end
|