effective_orders 1.0.0
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +856 -0
- data/Rakefile +24 -0
- data/app/assets/images/effective_orders/stripe_connect.png +0 -0
- data/app/assets/javascripts/effective_orders/shipping_address_toggle.js.coffee +30 -0
- data/app/assets/javascripts/effective_orders/stripe_charges.js.coffee +26 -0
- data/app/assets/javascripts/effective_orders/stripe_subscriptions.js.coffee +28 -0
- data/app/assets/javascripts/effective_orders.js +2 -0
- data/app/assets/stylesheets/effective_orders/_order.scss +30 -0
- data/app/assets/stylesheets/effective_orders.css.scss +1 -0
- data/app/controllers/admin/customers_controller.rb +15 -0
- data/app/controllers/admin/orders_controller.rb +22 -0
- data/app/controllers/effective/carts_controller.rb +70 -0
- data/app/controllers/effective/orders_controller.rb +191 -0
- data/app/controllers/effective/providers/moneris.rb +94 -0
- data/app/controllers/effective/providers/paypal.rb +29 -0
- data/app/controllers/effective/providers/stripe.rb +125 -0
- data/app/controllers/effective/providers/stripe_connect.rb +47 -0
- data/app/controllers/effective/subscriptions_controller.rb +123 -0
- data/app/controllers/effective/webhooks_controller.rb +86 -0
- data/app/helpers/effective_carts_helper.rb +90 -0
- data/app/helpers/effective_orders_helper.rb +108 -0
- data/app/helpers/effective_paypal_helper.rb +37 -0
- data/app/helpers/effective_stripe_helper.rb +63 -0
- data/app/mailers/effective/orders_mailer.rb +64 -0
- data/app/models/concerns/acts_as_purchasable.rb +134 -0
- data/app/models/effective/access_denied.rb +17 -0
- data/app/models/effective/cart.rb +65 -0
- data/app/models/effective/cart_item.rb +40 -0
- data/app/models/effective/customer.rb +61 -0
- data/app/models/effective/datatables/customers.rb +45 -0
- data/app/models/effective/datatables/orders.rb +53 -0
- data/app/models/effective/order.rb +247 -0
- data/app/models/effective/order_item.rb +69 -0
- data/app/models/effective/stripe_charge.rb +35 -0
- data/app/models/effective/subscription.rb +95 -0
- data/app/models/inputs/price_field.rb +63 -0
- data/app/models/inputs/price_form_input.rb +7 -0
- data/app/models/inputs/price_formtastic_input.rb +9 -0
- data/app/models/inputs/price_input.rb +19 -0
- data/app/models/inputs/price_simple_form_input.rb +8 -0
- data/app/models/validators/effective/sold_out_validator.rb +7 -0
- data/app/views/active_admin/effective_orders/orders/_show.html.haml +70 -0
- data/app/views/admin/customers/_actions.html.haml +2 -0
- data/app/views/admin/customers/index.html.haml +10 -0
- data/app/views/admin/orders/index.html.haml +7 -0
- data/app/views/admin/orders/show.html.haml +11 -0
- data/app/views/effective/carts/_cart.html.haml +33 -0
- data/app/views/effective/carts/show.html.haml +18 -0
- data/app/views/effective/orders/_checkout_step_1.html.haml +39 -0
- data/app/views/effective/orders/_checkout_step_2.html.haml +18 -0
- data/app/views/effective/orders/_my_purchases.html.haml +15 -0
- data/app/views/effective/orders/_order.html.haml +4 -0
- data/app/views/effective/orders/_order_header.html.haml +21 -0
- data/app/views/effective/orders/_order_items.html.haml +39 -0
- data/app/views/effective/orders/_order_payment_details.html.haml +11 -0
- data/app/views/effective/orders/_order_shipping.html.haml +19 -0
- data/app/views/effective/orders/_order_user_fields.html.haml +10 -0
- data/app/views/effective/orders/checkout.html.haml +3 -0
- data/app/views/effective/orders/declined.html.haml +10 -0
- data/app/views/effective/orders/moneris/_form.html.haml +34 -0
- data/app/views/effective/orders/my_purchases.html.haml +6 -0
- data/app/views/effective/orders/my_sales.html.haml +28 -0
- data/app/views/effective/orders/new.html.haml +4 -0
- data/app/views/effective/orders/paypal/_form.html.haml +5 -0
- data/app/views/effective/orders/purchased.html.haml +10 -0
- data/app/views/effective/orders/show.html.haml +17 -0
- data/app/views/effective/orders/stripe/_form.html.haml +8 -0
- data/app/views/effective/orders/stripe/_subscription_fields.html.haml +7 -0
- data/app/views/effective/orders_mailer/order_receipt_to_admin.html.haml +8 -0
- data/app/views/effective/orders_mailer/order_receipt_to_buyer.html.haml +8 -0
- data/app/views/effective/orders_mailer/order_receipt_to_seller.html.haml +30 -0
- data/app/views/effective/subscriptions/index.html.haml +16 -0
- data/app/views/effective/subscriptions/new.html.haml +10 -0
- data/app/views/effective/subscriptions/show.html.haml +49 -0
- data/config/routes.rb +57 -0
- data/db/migrate/01_create_effective_orders.rb.erb +91 -0
- data/db/upgrade/02_upgrade_effective_orders_from03x.rb.erb +29 -0
- data/db/upgrade/upgrade_price_column_on_table.rb.erb +17 -0
- data/lib/effective_orders/engine.rb +52 -0
- data/lib/effective_orders/version.rb +3 -0
- data/lib/effective_orders.rb +76 -0
- data/lib/generators/effective_orders/install_generator.rb +38 -0
- data/lib/generators/effective_orders/upgrade_from03x_generator.rb +34 -0
- data/lib/generators/effective_orders/upgrade_price_column_generator.rb +34 -0
- data/lib/generators/templates/README +1 -0
- data/lib/generators/templates/effective_orders.rb +210 -0
- data/spec/controllers/carts_controller_spec.rb +143 -0
- data/spec/controllers/moneris_orders_controller_spec.rb +245 -0
- data/spec/controllers/orders_controller_spec.rb +418 -0
- data/spec/controllers/stripe_orders_controller_spec.rb +127 -0
- data/spec/controllers/webhooks_controller_spec.rb +79 -0
- data/spec/dummy/README.rdoc +8 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/product.rb +17 -0
- data/spec/dummy/app/models/product_with_float_price.rb +17 -0
- data/spec/dummy/app/models/user.rb +28 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config/application.rb +31 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +83 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/devise.rb +254 -0
- data/spec/dummy/config/initializers/effective_addresses.rb +15 -0
- data/spec/dummy/config/initializers/effective_orders.rb +22 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/schema.rb +142 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +487 -0
- data/spec/dummy/log/test.log +347 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/helpers/effective_orders_helper_spec.rb +21 -0
- data/spec/models/acts_as_purchasable_spec.rb +107 -0
- data/spec/models/customer_spec.rb +71 -0
- data/spec/models/factories_spec.rb +13 -0
- data/spec/models/order_item_spec.rb +35 -0
- data/spec/models/order_spec.rb +323 -0
- data/spec/models/stripe_charge_spec.rb +39 -0
- data/spec/models/subscription_spec.rb +103 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/support/factories.rb +118 -0
- metadata +387 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
class CreateEffectiveOrders < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
create_table <%= @orders_table_name %> do |t|
|
|
4
|
+
t.integer :user_id
|
|
5
|
+
t.string :purchase_state
|
|
6
|
+
t.datetime :purchased_at
|
|
7
|
+
|
|
8
|
+
t.text :payment
|
|
9
|
+
|
|
10
|
+
t.timestamps
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
add_index <%= @orders_table_name %>, :user_id
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
create_table <%= @order_items_table_name %> do |t|
|
|
17
|
+
t.integer :order_id
|
|
18
|
+
t.integer :seller_id
|
|
19
|
+
t.string :purchasable_type
|
|
20
|
+
t.integer :purchasable_id
|
|
21
|
+
|
|
22
|
+
t.string :title
|
|
23
|
+
t.integer :quantity
|
|
24
|
+
t.integer :price, :default => 0
|
|
25
|
+
t.boolean :tax_exempt
|
|
26
|
+
t.decimal :tax_rate, :precision => 5, :scale => 3, :default => 0.0
|
|
27
|
+
|
|
28
|
+
t.timestamps
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
add_index <%= @order_items_table_name %>, :order_id
|
|
32
|
+
add_index <%= @order_items_table_name %>, :purchasable_id
|
|
33
|
+
add_index <%= @order_items_table_name %>, [:purchasable_type, :purchasable_id]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
create_table <%= @carts_table_name %> do |t|
|
|
37
|
+
t.integer :user_id
|
|
38
|
+
t.timestamps
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
add_index <%= @carts_table_name %>, :user_id
|
|
42
|
+
|
|
43
|
+
create_table <%= @cart_items_table_name %> do |t|
|
|
44
|
+
t.integer :cart_id
|
|
45
|
+
t.string :purchasable_type
|
|
46
|
+
t.integer :purchasable_id
|
|
47
|
+
|
|
48
|
+
t.integer :quantity
|
|
49
|
+
|
|
50
|
+
t.timestamps
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
add_index <%= @cart_items_table_name %>, :cart_id
|
|
54
|
+
add_index <%= @cart_items_table_name %>, :purchasable_id
|
|
55
|
+
add_index <%= @cart_items_table_name %>, [:purchasable_type, :purchasable_id]
|
|
56
|
+
|
|
57
|
+
create_table <%= @customers_table_name %> do |t|
|
|
58
|
+
t.integer :user_id
|
|
59
|
+
t.string :stripe_customer_id
|
|
60
|
+
t.string :stripe_active_card
|
|
61
|
+
t.string :stripe_connect_access_token
|
|
62
|
+
|
|
63
|
+
t.timestamps
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
add_index <%= @customers_table_name %>, :user_id
|
|
67
|
+
|
|
68
|
+
create_table <%= @subscriptions_table_name %> do |t|
|
|
69
|
+
t.integer :customer_id
|
|
70
|
+
t.string :stripe_plan_id
|
|
71
|
+
t.string :stripe_subscription_id
|
|
72
|
+
t.string :stripe_coupon_id
|
|
73
|
+
t.string :title
|
|
74
|
+
t.integer :price, :default => 0
|
|
75
|
+
|
|
76
|
+
t.timestamps
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
add_index <%= @subscriptions_table_name %>, :customer_id
|
|
80
|
+
add_index <%= @subscriptions_table_name %>, :stripe_subscription_id
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def self.down
|
|
84
|
+
drop_table <%= @orders_table_name %>
|
|
85
|
+
drop_table <%= @order_items_table_name %>
|
|
86
|
+
drop_table <%= @carts_table_name %>
|
|
87
|
+
drop_table <%= @cart_items_table_name %>
|
|
88
|
+
drop_table <%= @customers_table_name %>
|
|
89
|
+
drop_table <%= @subscriptions_table_name %>
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
class UpgradeEffectiveOrdersFrom03x < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
prices = ActiveRecord::Base.connection.execute("SELECT price from <%= @order_items_table_name.gsub(':', '') %> LIMIT 10").values.flatten
|
|
4
|
+
if prices.blank? || prices.any? { |price| price.to_s.include?('.') }
|
|
5
|
+
ActiveRecord::Base.connection.execute("UPDATE <%= @order_items_table_name.gsub(':', '') %> O SET price = (O.price * 100.0)")
|
|
6
|
+
change_column <%= @order_items_table_name %>, :price, :integer, :default => 0
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
prices = ActiveRecord::Base.connection.execute("SELECT price from <%= @subscriptions_table_name.gsub(':', '') %> LIMIT 10").values.flatten
|
|
10
|
+
if prices.blank? || prices.any? { |price| price.to_s.include?('.') }
|
|
11
|
+
ActiveRecord::Base.connection.execute("UPDATE <%= @subscriptions_table_name.gsub(':', '') %> O SET price = (O.price * 100.0)")
|
|
12
|
+
change_column <%= @subscriptions_table_name %>, :price, :integer, :default => 0
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.down
|
|
17
|
+
prices = ActiveRecord::Base.connection.execute("SELECT price from <%= @order_items_table_name.gsub(':', '') %> LIMIT 10").values.flatten
|
|
18
|
+
if prices.none? { |price| price.to_s.include?('.') }
|
|
19
|
+
change_column <%= @order_items_table_name %>, :price, :decimal, :precision => 8, :scale => 2, :default => 0.0
|
|
20
|
+
ActiveRecord::Base.connection.execute("UPDATE <%= @order_items_table_name.gsub(':', '') %> O SET price = (O.price / 100.0)")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
prices = ActiveRecord::Base.connection.execute("SELECT price from <%= @subscriptions_table_name.gsub(':', '') %> LIMIT 10").values.flatten
|
|
24
|
+
if prices.none? { |price| price.to_s.include?('.') }
|
|
25
|
+
change_column <%= @subscriptions_table_name %>, :price, :decimal, :precision => 8, :scale => 2, :default => 0.0
|
|
26
|
+
ActiveRecord::Base.connection.execute("UPDATE <%= @subscriptions_table_name.gsub(':', '') %> O SET price = (O.price / 100.0)")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class UpgradePriceColumnOn<%= @table.capitalize %> < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
prices = ActiveRecord::Base.connection.execute("SELECT <%= @column %> FROM <%= @table %> LIMIT 10").values.flatten
|
|
4
|
+
if prices.blank? || prices.any? { |<%= @column %>| <%= @column %>.to_s.include?('.') }
|
|
5
|
+
ActiveRecord::Base.connection.execute("UPDATE <%= @table %> O SET <%= @column %> = (O.<%= @column %> * 100.0)")
|
|
6
|
+
change_column :<%= @table %>, :<%= @column %>, :integer, :default => 0
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.down
|
|
11
|
+
prices = ActiveRecord::Base.connection.execute("SELECT price FROM <%= @table %> LIMIT 10").values.flatten
|
|
12
|
+
if prices.none? { |<%= @column %>| <%= @column %>.to_s.include?('.') }
|
|
13
|
+
change_column :<%= @table %>, :<%= @column %>, :decimal, :precision => 8, :scale => 2, :default => 0.0
|
|
14
|
+
ActiveRecord::Base.connection.execute("UPDATE <%= @table %> O SET <%= @column %> = (O.<%= @column %> / 100.0)")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module EffectiveOrders
|
|
2
|
+
class Engine < ::Rails::Engine
|
|
3
|
+
engine_name 'effective_orders'
|
|
4
|
+
|
|
5
|
+
config.autoload_paths += Dir["#{config.root}/app/models/**/"]
|
|
6
|
+
|
|
7
|
+
# Include Helpers to base application
|
|
8
|
+
initializer 'effective_orders.action_controller' do |app|
|
|
9
|
+
ActiveSupport.on_load :action_controller do
|
|
10
|
+
helper EffectiveOrdersHelper
|
|
11
|
+
helper EffectiveCartsHelper
|
|
12
|
+
helper EffectivePaypalHelper if EffectiveOrders.paypal_enabled
|
|
13
|
+
helper EffectiveStripeHelper if EffectiveOrders.stripe_enabled
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Include acts_as_addressable concern and allow any ActiveRecord object to call it
|
|
18
|
+
initializer 'effective_orders.active_record' do |app|
|
|
19
|
+
ActiveSupport.on_load :active_record do
|
|
20
|
+
ActiveRecord::Base.extend(ActsAsPurchasable::ActiveRecord)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
initializer 'effective_orders.action_view' do |app|
|
|
25
|
+
ActiveSupport.on_load :action_view do
|
|
26
|
+
ActionView::Helpers::FormBuilder.send(:include, Inputs::PriceFormInput)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Set up our default configuration options.
|
|
31
|
+
initializer "effective_orders.defaults", :before => :load_config_initializers do |app|
|
|
32
|
+
eval File.read("#{config.root}/lib/generators/templates/effective_orders.rb")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Set up our Stripe API Key
|
|
36
|
+
initializer "effective_orders.stripe_api_key", :after => :load_config_initializers do |app|
|
|
37
|
+
if EffectiveOrders.stripe_enabled
|
|
38
|
+
require 'stripe'
|
|
39
|
+
::Stripe.api_key = EffectiveOrders.stripe[:secret_key]
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# ActiveAdmin (optional)
|
|
44
|
+
# This prepends the load path so someone can override the assets.rb if they want.
|
|
45
|
+
initializer 'effective_orders.active_admin' do
|
|
46
|
+
if defined?(ActiveAdmin) && EffectiveOrders.use_active_admin == true
|
|
47
|
+
ActiveAdmin.application.load_paths.unshift Dir["#{config.root}/active_admin"]
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require 'effective_addresses'
|
|
2
|
+
require "effective_orders/engine"
|
|
3
|
+
require 'migrant' # Required for rspec to run properly
|
|
4
|
+
|
|
5
|
+
module EffectiveOrders
|
|
6
|
+
PURCHASED = 'purchased'
|
|
7
|
+
DECLINED = 'declined'
|
|
8
|
+
|
|
9
|
+
# The following are all valid config keys
|
|
10
|
+
mattr_accessor :orders_table_name
|
|
11
|
+
mattr_accessor :order_items_table_name
|
|
12
|
+
mattr_accessor :carts_table_name
|
|
13
|
+
mattr_accessor :cart_items_table_name
|
|
14
|
+
mattr_accessor :customers_table_name
|
|
15
|
+
mattr_accessor :subscriptions_table_name
|
|
16
|
+
|
|
17
|
+
mattr_accessor :authorization_method
|
|
18
|
+
mattr_accessor :tax_rate_method
|
|
19
|
+
|
|
20
|
+
mattr_accessor :layout
|
|
21
|
+
mattr_accessor :simple_form_options
|
|
22
|
+
mattr_accessor :use_active_admin
|
|
23
|
+
mattr_accessor :obfuscate_order_ids
|
|
24
|
+
mattr_accessor :silence_deprecation_warnings
|
|
25
|
+
mattr_accessor :allow_pretend_purchase_in_production
|
|
26
|
+
|
|
27
|
+
mattr_accessor :require_billing_address
|
|
28
|
+
mattr_accessor :require_shipping_address
|
|
29
|
+
|
|
30
|
+
mattr_accessor :collect_user_fields
|
|
31
|
+
mattr_accessor :skip_user_validation
|
|
32
|
+
|
|
33
|
+
mattr_accessor :minimum_charge
|
|
34
|
+
mattr_accessor :allow_free_orders
|
|
35
|
+
|
|
36
|
+
mattr_accessor :paypal_enabled
|
|
37
|
+
mattr_accessor :moneris_enabled
|
|
38
|
+
|
|
39
|
+
# application fee is required if stripe_connect_enabled is true
|
|
40
|
+
mattr_accessor :stripe_enabled
|
|
41
|
+
|
|
42
|
+
mattr_accessor :stripe_subscriptions_enabled
|
|
43
|
+
mattr_accessor :stripe_connect_enabled
|
|
44
|
+
mattr_accessor :stripe_connect_application_fee_method
|
|
45
|
+
|
|
46
|
+
# These are hashes of configs
|
|
47
|
+
mattr_accessor :mailer
|
|
48
|
+
mattr_accessor :paypal
|
|
49
|
+
mattr_accessor :moneris
|
|
50
|
+
mattr_accessor :stripe
|
|
51
|
+
|
|
52
|
+
def self.setup
|
|
53
|
+
yield self
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.authorized?(controller, action, resource)
|
|
57
|
+
if authorization_method.respond_to?(:call) || authorization_method.kind_of?(Symbol)
|
|
58
|
+
raise Effective::AccessDenied.new() unless (controller || self).instance_exec(controller, action, resource, &authorization_method)
|
|
59
|
+
end
|
|
60
|
+
true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.minimum_charge
|
|
64
|
+
if @@minimum_charge.nil? || @@minimum_charge.kind_of?(Integer)
|
|
65
|
+
@@minimum_charge
|
|
66
|
+
else
|
|
67
|
+
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).floor conversion') unless EffectiveOrders.silence_deprecation_warnings
|
|
68
|
+
((@@minimum_charge * 100.0).floor rescue nil)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
class SoldOutException < Exception; end
|
|
73
|
+
class AlreadyPurchasedException < Exception; end
|
|
74
|
+
class AlreadyDeclinedException < Exception; end
|
|
75
|
+
|
|
76
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module EffectiveOrders
|
|
2
|
+
module Generators
|
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
|
4
|
+
include Rails::Generators::Migration
|
|
5
|
+
|
|
6
|
+
desc "Creates an EffectiveOrders initializer in your application."
|
|
7
|
+
|
|
8
|
+
source_root File.expand_path("../../templates", __FILE__)
|
|
9
|
+
|
|
10
|
+
def self.next_migration_number(dirname)
|
|
11
|
+
if not ActiveRecord::Base.timestamped_migrations
|
|
12
|
+
Time.new.utc.strftime("%Y%m%d%H%M%S")
|
|
13
|
+
else
|
|
14
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def copy_initializer
|
|
19
|
+
template "effective_orders.rb", "config/initializers/effective_orders.rb"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def create_migration_file
|
|
23
|
+
@orders_table_name = ':' + EffectiveOrders.orders_table_name.to_s
|
|
24
|
+
@order_items_table_name = ':' + EffectiveOrders.order_items_table_name.to_s
|
|
25
|
+
@carts_table_name = ':' + EffectiveOrders.carts_table_name.to_s
|
|
26
|
+
@cart_items_table_name = ':' + EffectiveOrders.cart_items_table_name.to_s
|
|
27
|
+
@customers_table_name = ':' + EffectiveOrders.customers_table_name.to_s
|
|
28
|
+
@subscriptions_table_name = ':' + EffectiveOrders.subscriptions_table_name.to_s
|
|
29
|
+
|
|
30
|
+
migration_template '../../../db/migrate/01_create_effective_orders.rb.erb', 'db/migrate/create_effective_orders.rb'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def show_readme
|
|
34
|
+
readme "README" if behavior == :invoke
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module EffectiveOrders
|
|
2
|
+
module Generators
|
|
3
|
+
class UpgradeFrom03xGenerator < Rails::Generators::Base
|
|
4
|
+
include Rails::Generators::Migration
|
|
5
|
+
|
|
6
|
+
desc "Upgrade effective_orders from the 0.3.x branch"
|
|
7
|
+
|
|
8
|
+
source_root File.expand_path("../../templates", __FILE__)
|
|
9
|
+
|
|
10
|
+
def self.next_migration_number(dirname)
|
|
11
|
+
if not ActiveRecord::Base.timestamped_migrations
|
|
12
|
+
Time.new.utc.strftime("%Y%m%d%H%M%S")
|
|
13
|
+
else
|
|
14
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create_migration_file
|
|
19
|
+
@orders_table_name = ':' + EffectiveOrders.orders_table_name.to_s
|
|
20
|
+
@order_items_table_name = ':' + EffectiveOrders.order_items_table_name.to_s
|
|
21
|
+
@carts_table_name = ':' + EffectiveOrders.carts_table_name.to_s
|
|
22
|
+
@cart_items_table_name = ':' + EffectiveOrders.cart_items_table_name.to_s
|
|
23
|
+
@customers_table_name = ':' + EffectiveOrders.customers_table_name.to_s
|
|
24
|
+
@subscriptions_table_name = ':' + EffectiveOrders.subscriptions_table_name.to_s
|
|
25
|
+
|
|
26
|
+
migration_template '../../../db/upgrade/02_upgrade_effective_orders_from03x.rb.erb', 'db/migrate/upgrade_effective_orders_from03x.rb'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def show_readme
|
|
30
|
+
readme "README" if behavior == :invoke
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# bundle exec rails generate effective_orders:upgrade_price_column TABLE COLUMN
|
|
2
|
+
|
|
3
|
+
module EffectiveOrders
|
|
4
|
+
module Generators
|
|
5
|
+
class UpgradePriceColumn < Rails::Generators::Base
|
|
6
|
+
include Rails::Generators::Migration
|
|
7
|
+
|
|
8
|
+
desc "Upgrade a table with a decimal column to integer"
|
|
9
|
+
|
|
10
|
+
source_root File.expand_path("../../templates", __FILE__)
|
|
11
|
+
argument :table, :type => :string, :default => nil
|
|
12
|
+
argument :column, :type => :string, :default => :price
|
|
13
|
+
|
|
14
|
+
def self.next_migration_number(dirname)
|
|
15
|
+
if not ActiveRecord::Base.timestamped_migrations
|
|
16
|
+
Time.new.utc.strftime("%Y%m%d%H%M%S")
|
|
17
|
+
else
|
|
18
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def create_migration_file
|
|
23
|
+
@table = table.to_s.downcase
|
|
24
|
+
@column = column.to_s.downcase
|
|
25
|
+
|
|
26
|
+
migration_template '../../../db/upgrade/upgrade_price_column_on_table.rb.erb', "db/migrate/upgrade_price_column_on_#{table}.rb"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def show_readme
|
|
30
|
+
readme "README" if behavior == :invoke
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Thanks for using EffectiveOrders
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# EffectiveOrders Rails Engine
|
|
2
|
+
|
|
3
|
+
EffectiveOrders.setup do |config|
|
|
4
|
+
# Configure Database Tables
|
|
5
|
+
config.orders_table_name = :orders
|
|
6
|
+
config.order_items_table_name = :order_items
|
|
7
|
+
config.carts_table_name = :carts
|
|
8
|
+
config.cart_items_table_name = :cart_items
|
|
9
|
+
config.customers_table_name = :customers
|
|
10
|
+
config.subscriptions_table_name = :subscriptions
|
|
11
|
+
|
|
12
|
+
# Authorization Method
|
|
13
|
+
#
|
|
14
|
+
# This method is called by all controller actions with the appropriate action and resource
|
|
15
|
+
# If the method returns false, an Effective::AccessDenied Error will be raised (see README.md for complete info)
|
|
16
|
+
#
|
|
17
|
+
# Use via Proc (and with CanCan):
|
|
18
|
+
# config.authorization_method = Proc.new { |controller, action, resource| can?(action, resource) }
|
|
19
|
+
#
|
|
20
|
+
# Use via custom method:
|
|
21
|
+
# config.authorization_method = :my_authorization_method
|
|
22
|
+
#
|
|
23
|
+
# And then in your application_controller.rb:
|
|
24
|
+
#
|
|
25
|
+
# def my_authorization_method(action, resource)
|
|
26
|
+
# current_user.is?(:admin)
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
# Or disable the check completely:
|
|
30
|
+
# config.authorization_method = false
|
|
31
|
+
config.authorization_method = Proc.new { |controller, action, resource| can?(action, resource) } # CanCan gem
|
|
32
|
+
|
|
33
|
+
# Register Effective::Order with ActiveAdmin if ActiveAdmin is present
|
|
34
|
+
config.use_active_admin = true
|
|
35
|
+
|
|
36
|
+
# Use effective_obfuscation gem to change order.id into a seemingly random 10-digit number
|
|
37
|
+
config.obfuscate_order_ids = true
|
|
38
|
+
|
|
39
|
+
# Silence the price deprecation warnings
|
|
40
|
+
config.silence_deprecation_warnings = false
|
|
41
|
+
|
|
42
|
+
# Require these addresses when creating a new Order. Works with effective_addresses gem
|
|
43
|
+
config.require_billing_address = true
|
|
44
|
+
config.require_shipping_address = false
|
|
45
|
+
|
|
46
|
+
# If set, the orders#new screen will render effective/orders/user_fields partial and capture this User Info
|
|
47
|
+
# The partial can be overridden to customize the form, but the following fields are also fed into strong_paramters
|
|
48
|
+
config.collect_user_fields = []
|
|
49
|
+
#config.collect_user_fields = [:salutation, :first_name, :last_name] # Must be valid fields on the User object
|
|
50
|
+
|
|
51
|
+
# Don't validate_associated :user when saving an Order
|
|
52
|
+
config.skip_user_validation = false
|
|
53
|
+
|
|
54
|
+
# Tax Calculation Method
|
|
55
|
+
config.tax_rate_method = Proc.new { |acts_as_purchasable| 0.05 } # Regardless of the object, charge 5% tax (GST)
|
|
56
|
+
|
|
57
|
+
# Minimum Charge
|
|
58
|
+
# Prevent orders less than this value from being purchased
|
|
59
|
+
# Stripe doesn't allow orders less than $0.50
|
|
60
|
+
# Set to nil for no minimum charge
|
|
61
|
+
# Default value is 50 cents, or $0.50
|
|
62
|
+
config.minimum_charge = 50
|
|
63
|
+
|
|
64
|
+
# Free Orders
|
|
65
|
+
# Allow orders with a total of 0.00 to be purchased (regardless of the minimum charge setting)
|
|
66
|
+
# When enabled, the checkout process will skip the paypal/stripe/purchasing step
|
|
67
|
+
# and just display the 'Thank You' after checkout is clicked
|
|
68
|
+
config.allow_free_orders = true
|
|
69
|
+
|
|
70
|
+
# Allow Pretend Purchase in Production
|
|
71
|
+
# WARNING: Setting this option to true will allow users to purchase! an Order without entering a credit card
|
|
72
|
+
# WARNING: When true, users can purchase! anything without paying money
|
|
73
|
+
#
|
|
74
|
+
# This should basically always be false, but sometimes you want to make a Beta/Demo site
|
|
75
|
+
# where users may test the purchase workflow without actually paying money
|
|
76
|
+
#
|
|
77
|
+
# When true, there will be a 'Process Order' button on the Checkout screen.
|
|
78
|
+
# Clicking this button will mark an Order purchased and redirect the user to the
|
|
79
|
+
# Thank You page just as if they had successfully Checked Out through a payment processor
|
|
80
|
+
config.allow_pretend_purchase_in_production = false
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# Layout Settings
|
|
84
|
+
# Configure the Layout per controller, or all at once
|
|
85
|
+
|
|
86
|
+
# config.layout = 'application' # All EffectiveOrders controllers will use this layout
|
|
87
|
+
config.layout = {
|
|
88
|
+
:carts => 'application',
|
|
89
|
+
:orders => 'application',
|
|
90
|
+
:subscriptions => 'application',
|
|
91
|
+
:admin_customers => 'application',
|
|
92
|
+
:admin_orders => 'application'
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# SimpleForm Options
|
|
96
|
+
# This Hash of options will be passed into any simple_form_for() calls
|
|
97
|
+
config.simple_form_options = {}
|
|
98
|
+
|
|
99
|
+
# config.simple_form_options = {
|
|
100
|
+
# :html => {:class => 'form-horizontal'},
|
|
101
|
+
# :wrapper => :horizontal_form,
|
|
102
|
+
# :wrapper_mappings => {
|
|
103
|
+
# :boolean => :horizontal_boolean,
|
|
104
|
+
# :check_boxes => :horizontal_radio_and_checkboxes,
|
|
105
|
+
# :radio_buttons => :horizontal_radio_and_checkboxes
|
|
106
|
+
# }
|
|
107
|
+
# }
|
|
108
|
+
|
|
109
|
+
# Mailer Settings
|
|
110
|
+
# effective_orders will send out receipts to the buyer, seller and admins.
|
|
111
|
+
# For all the emails, the same :subject_prefix will be prefixed. Leave as nil / empty string if you don't want any prefix
|
|
112
|
+
#
|
|
113
|
+
# The subject_for_admin_receipt, subject_for_buyer_receipt and subject_for_seller_receipt can be one of:
|
|
114
|
+
# - nil / empty string to use the built in defaults
|
|
115
|
+
# - A string with the full subject line for this email
|
|
116
|
+
# - A Proc to create the subject line based on the email
|
|
117
|
+
# In all three of these cases, the subject_prefix will still be used.
|
|
118
|
+
|
|
119
|
+
# The Procs are the same for admin & buyer receipt, the seller Proc is different
|
|
120
|
+
# :subject_for_admin_receipt => Proc.new { |order| "Order #{order.to_param} has been purchased"}
|
|
121
|
+
# :subject_for_buyer_receipt => Proc.new { |order| "Order #{order.to_param} has been purchased"}
|
|
122
|
+
# :subject_for_seller_receipt => Proc.new { |order, order_items, seller| "Order #{order.to_param} has been purchased"}
|
|
123
|
+
|
|
124
|
+
config.mailer = {
|
|
125
|
+
:send_order_receipt_to_admin => true,
|
|
126
|
+
:send_order_receipt_to_buyer => true,
|
|
127
|
+
:send_order_receipt_to_seller => true, # Only applies to StripeConnect
|
|
128
|
+
:admin_email => 'admin@example.com',
|
|
129
|
+
:default_from => 'info@example.com',
|
|
130
|
+
:subject_prefix => '[example]',
|
|
131
|
+
:subject_for_admin_receipt => '',
|
|
132
|
+
:subject_for_buyer_receipt => '',
|
|
133
|
+
:subject_for_seller_receipt => ''
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
# Moneris configuration
|
|
137
|
+
config.moneris_enabled = false
|
|
138
|
+
|
|
139
|
+
if Rails.env.production?
|
|
140
|
+
config.moneris = {
|
|
141
|
+
:ps_store_id => '',
|
|
142
|
+
:hpp_key => '',
|
|
143
|
+
:hpp_url => 'https://www3.moneris.com/HPPDP/index.php',
|
|
144
|
+
:verify_url => 'https://www3.moneris.com/HPPDP/verifyTxn.php',
|
|
145
|
+
:order_nudge => 0
|
|
146
|
+
}
|
|
147
|
+
else
|
|
148
|
+
config.moneris = {
|
|
149
|
+
:ps_store_id => '',
|
|
150
|
+
:hpp_key => '',
|
|
151
|
+
:hpp_url => 'https://esqa.moneris.com/HPPDP/index.php',
|
|
152
|
+
:verify_url => 'https://esqa.moneris.com/HPPDP/verifyTxn.php',
|
|
153
|
+
:order_nudge => 0
|
|
154
|
+
}
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Paypal configuration
|
|
158
|
+
config.paypal_enabled = false
|
|
159
|
+
|
|
160
|
+
if Rails.env.production?
|
|
161
|
+
config.paypal = {
|
|
162
|
+
:seller_email => '',
|
|
163
|
+
:secret => '',
|
|
164
|
+
:cert_id => '',
|
|
165
|
+
:paypal_url => 'https://www.paypal.com/cgi-bin/webscr',
|
|
166
|
+
:currency => 'CAD',
|
|
167
|
+
:paypal_cert => "#{Rails.root}/config/paypalcerts/production/paypal_cert.pem",
|
|
168
|
+
:app_cert => "#{Rails.root}/config/paypalcerts/production/app_cert.pem",
|
|
169
|
+
:app_key => "#{Rails.root}/config/paypalcerts/production/app_key.pem"
|
|
170
|
+
}
|
|
171
|
+
else
|
|
172
|
+
config.paypal = {
|
|
173
|
+
:seller_email => '',
|
|
174
|
+
:secret => '',
|
|
175
|
+
:cert_id => '',
|
|
176
|
+
:paypal_url => 'https://www.sandbox.paypal.com/cgi-bin/webscr',
|
|
177
|
+
:currency => 'CAD',
|
|
178
|
+
:paypal_cert => "#{Rails.root}/config/paypalcerts/#{Rails.env}/paypal_cert.pem",
|
|
179
|
+
:app_cert => "#{Rails.root}/config/paypalcerts/#{Rails.env}/app_cert.pem",
|
|
180
|
+
:app_key => "#{Rails.root}/config/paypalcerts/#{Rails.env}/app_key.pem"
|
|
181
|
+
}
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Stripe configuration
|
|
185
|
+
config.stripe_enabled = false
|
|
186
|
+
config.stripe_subscriptions_enabled = false # https://stripe.com/docs/subscriptions
|
|
187
|
+
config.stripe_connect_enabled = false # https://stripe.com/docs/connect
|
|
188
|
+
config.stripe_connect_application_fee_method = Proc.new { |order_item| order_item.total * 0.10 } # 10 percent
|
|
189
|
+
|
|
190
|
+
if Rails.env.production?
|
|
191
|
+
config.stripe = {
|
|
192
|
+
:secret_key => '',
|
|
193
|
+
:publishable_key => '',
|
|
194
|
+
:currency => 'usd',
|
|
195
|
+
:site_title => 'My Site',
|
|
196
|
+
:site_image => '', # A relative URL pointing to a square image of your brand or product. The recommended minimum size is 128x128px.
|
|
197
|
+
:connect_client_id => ''
|
|
198
|
+
}
|
|
199
|
+
else
|
|
200
|
+
config.stripe = {
|
|
201
|
+
:secret_key => '',
|
|
202
|
+
:publishable_key => '',
|
|
203
|
+
:currency => 'usd',
|
|
204
|
+
:site_title => 'My Development Site', # Displayed on the Embedded Stripe Form
|
|
205
|
+
:site_image => '', # A relative URL pointing to a square image of your brand or product. The recommended minimum size is 128x128px.
|
|
206
|
+
:connect_client_id => ''
|
|
207
|
+
}
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
end
|