effective_orders 1.8.1 → 2.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 +150 -60
- data/Rakefile +0 -3
- data/active_admin/effective_orders.rb +14 -9
- data/app/assets/javascripts/effective_orders.js +2 -0
- data/app/assets/javascripts/effective_orders/{stripe_charges.js.coffee → providers/stripe_charges.js.coffee} +1 -1
- data/app/assets/javascripts/effective_orders/{stripe_subscriptions.js.coffee → providers/stripe_subscriptions.js.coffee} +1 -1
- data/app/assets/stylesheets/effective_orders/_order.scss +9 -3
- data/app/controllers/admin/orders_controller.rb +87 -3
- data/app/controllers/concerns/acts_as_active_admin_controller.rb +2 -1
- data/app/controllers/effective/carts_controller.rb +4 -2
- data/app/controllers/effective/orders_controller.rb +101 -60
- data/app/controllers/effective/providers/app_checkout.rb +10 -2
- data/app/controllers/effective/providers/ccbill.rb +34 -0
- data/app/controllers/effective/providers/cheque.rb +30 -0
- data/app/controllers/effective/providers/moneris.rb +7 -7
- data/app/controllers/effective/providers/paypal.rb +7 -5
- data/app/controllers/effective/providers/pretend.rb +22 -0
- data/app/controllers/effective/providers/stripe.rb +26 -24
- data/app/controllers/effective/webhooks_controller.rb +1 -1
- data/app/helpers/effective_carts_helper.rb +59 -29
- data/app/helpers/effective_ccbill_helper.rb +25 -0
- data/app/helpers/effective_orders_helper.rb +50 -41
- data/app/helpers/effective_paypal_helper.rb +11 -11
- data/app/mailers/effective/orders_mailer.rb +95 -20
- data/app/models/concerns/acts_as_purchasable.rb +14 -22
- data/app/models/effective/cart.rb +9 -15
- data/app/models/effective/cart_item.rb +15 -13
- data/app/models/effective/customer.rb +9 -9
- data/app/models/effective/datatables/order_items.rb +14 -8
- data/app/models/effective/datatables/orders.rb +56 -69
- data/app/models/effective/order.rb +250 -139
- data/app/models/effective/order_item.rb +23 -16
- data/app/models/effective/product.rb +23 -0
- data/app/models/effective/providers/ccbill_postback.rb +85 -0
- data/app/models/effective/{stripe_charge.rb → providers/stripe_charge.rb} +1 -1
- data/app/models/effective/subscription.rb +16 -12
- data/app/models/effective/tax_rate_calculator.rb +45 -0
- data/app/views/admin/customers/index.html.haml +2 -5
- data/app/views/admin/order_items/index.html.haml +2 -5
- data/app/views/admin/orders/_actions.html.haml +2 -0
- data/app/views/admin/orders/_form.html.haml +28 -0
- data/app/views/admin/orders/_order_item_fields.html.haml +9 -0
- data/app/views/admin/orders/index.html.haml +9 -5
- data/app/views/admin/orders/new.html.haml +3 -0
- data/app/views/effective/carts/_cart.html.haml +3 -12
- data/app/views/effective/carts/_cart_actions.html.haml +4 -0
- data/app/views/effective/carts/show.html.haml +10 -12
- data/app/views/effective/orders/_checkout_step1.html.haml +46 -0
- data/app/views/effective/orders/_checkout_step2.html.haml +33 -0
- data/app/views/effective/orders/_order.html.haml +2 -0
- data/app/views/effective/orders/_order_actions.html.haml +10 -5
- data/app/views/effective/orders/_order_footer.html.haml +1 -0
- data/app/views/effective/orders/_order_items.html.haml +11 -9
- data/app/views/effective/orders/_order_note.html.haml +8 -0
- data/app/views/effective/orders/_order_note_fields.html.haml +5 -0
- data/app/views/effective/orders/_order_shipping.html.haml +4 -4
- data/app/views/effective/orders/_order_user_fields.html.haml +1 -0
- data/app/views/effective/orders/_orders_table.html.haml +27 -0
- data/app/views/effective/orders/ccbill/_form.html.haml +24 -0
- data/app/views/effective/orders/checkout_step1.html.haml +3 -0
- data/app/views/effective/orders/checkout_step2.html.haml +3 -0
- data/app/views/effective/orders/cheque/_form.html.haml +2 -0
- data/app/views/effective/orders/cheque/pay_by_cheque.html.haml +9 -0
- data/app/views/effective/orders/declined.html.haml +4 -2
- data/app/views/effective/orders/my_purchases.html.haml +1 -1
- data/app/views/effective/orders/my_sales.html.haml +1 -1
- data/app/views/effective/orders/purchased.html.haml +3 -2
- data/app/views/effective/orders/show.html.haml +1 -1
- data/app/views/effective/orders/stripe/_form.html.haml +5 -5
- data/app/views/effective/orders_mailer/order_error.html.haml +11 -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/layouts/effective_orders_mailer_layout.html.haml +7 -7
- data/config/routes.rb +39 -24
- data/db/migrate/01_create_effective_orders.rb.erb +20 -1
- data/db/upgrade/03_upgrade_effective_orders_from1x.rb.erb +95 -0
- data/lib/effective_orders.rb +67 -9
- data/lib/effective_orders/app_checkout_service.rb +1 -2
- data/lib/effective_orders/engine.rb +46 -14
- data/lib/effective_orders/version.rb +1 -1
- data/lib/generators/effective_orders/install_generator.rb +1 -0
- data/lib/generators/effective_orders/upgrade_from03x_generator.rb +1 -0
- data/lib/generators/effective_orders/upgrade_from1x_generator.rb +31 -0
- data/lib/generators/templates/effective_orders.rb +131 -66
- data/lib/generators/templates/effective_orders_mailer_preview.rb +28 -13
- data/spec/controllers/admin/orders_controller_spec.rb +242 -0
- data/spec/controllers/ccbill_orders_controller_spec.rb +103 -0
- data/spec/controllers/moneris_orders_controller_spec.rb +23 -23
- data/spec/controllers/orders_controller_spec.rb +167 -79
- data/spec/controllers/stripe_orders_controller_spec.rb +7 -7
- data/spec/dummy/app/models/product.rb +0 -8
- data/spec/dummy/app/models/product_with_float_price.rb +0 -8
- data/spec/dummy/app/models/user.rb +2 -19
- data/spec/dummy/config/application.rb +2 -1
- data/spec/dummy/config/environments/test.rb +1 -0
- data/spec/dummy/config/initializers/effective_orders.rb +109 -64
- data/spec/dummy/db/schema.rb +15 -2
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/test.log +0 -258
- data/spec/models/acts_as_purchasable_spec.rb +8 -6
- data/spec/models/factories_spec.rb +7 -1
- data/spec/models/order_item_spec.rb +1 -1
- data/spec/models/order_spec.rb +165 -46
- data/spec/models/stripe_charge_spec.rb +5 -5
- data/spec/spec_helper.rb +2 -0
- data/spec/support/factories.rb +49 -33
- metadata +47 -64
- data/app/views/effective/orders/_checkout_step_1.html.haml +0 -43
- data/app/views/effective/orders/_checkout_step_2.html.haml +0 -25
- data/app/views/effective/orders/_my_purchases.html.haml +0 -17
- data/app/views/effective/orders/checkout.html.haml +0 -3
- data/app/views/effective/orders/new.html.haml +0 -4
- data/spec/dummy/log/development.log +0 -82
@@ -6,24 +6,27 @@ module Effective
|
|
6
6
|
belongs_to :purchasable, :polymorphic => true
|
7
7
|
belongs_to :seller, :class_name => 'User'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
quantity :integer, :validates => [:presence, :numericality]
|
12
|
-
price :integer, :default => 0, :validates => [:numericality]
|
13
|
-
tax_exempt :boolean, :validates => [:inclusion => {:in => [true, false]}]
|
14
|
-
tax_rate :decimal, :precision => 5, :scale => 3, :default => 0.000, :validates => [:presence]
|
9
|
+
delegate :purchased_download_url, :to => :purchasable
|
10
|
+
delegate :purchased?, :declined?, :to => :order
|
15
11
|
|
16
|
-
|
17
|
-
|
12
|
+
# structure do
|
13
|
+
# title :string
|
14
|
+
# quantity :integer
|
15
|
+
# price :integer, default: 0
|
16
|
+
# tax_exempt :boolean
|
17
|
+
#
|
18
|
+
# timestamps
|
19
|
+
# end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
accepts_nested_attributes_for :purchasable, :allow_destroy => false, :reject_if => :all_blank, :update_only => true
|
21
|
+
validates :purchasable, associated: true, presence: true
|
22
|
+
accepts_nested_attributes_for :purchasable, allow_destroy: false, reject_if: :all_blank, update_only: true
|
22
23
|
|
23
|
-
|
24
|
+
validates :title, presence: true
|
25
|
+
validates :quantity, presence: true, numericality: { greater_than: 0 }
|
26
|
+
validates :price, numericality: true
|
27
|
+
validates :tax_exempt, inclusion: { in: [true, false] }
|
24
28
|
|
25
|
-
|
26
|
-
delegate :purchased?, :declined?, :to => :order
|
29
|
+
validates :seller_id, presence: true, if: Proc.new { |order_item| EffectiveOrders.stripe_connect_enabled }
|
27
30
|
|
28
31
|
scope :sold, -> { joins(:order).where(:orders => {:purchase_state => EffectiveOrders::PURCHASED}) }
|
29
32
|
scope :sold_by, lambda { |user| sold().where(:seller_id => user.try(:id)) }
|
@@ -36,11 +39,15 @@ module Effective
|
|
36
39
|
price * quantity
|
37
40
|
end
|
38
41
|
|
39
|
-
def tax
|
40
|
-
|
42
|
+
def tax
|
43
|
+
return 0 if tax_exempt?
|
44
|
+
raise 'parent Effective::Order must have a tax_rate to compute order item tax' unless order.try(:tax_rate).present?
|
45
|
+
(subtotal * order.tax_rate / 100.0).round(0).to_i
|
41
46
|
end
|
42
47
|
|
43
48
|
def total
|
49
|
+
return subtotal if tax_exempt?
|
50
|
+
raise 'parent Effective::Order must have a tax_rate to compute order item total' unless order.try(:tax_rate).present?
|
44
51
|
subtotal + tax
|
45
52
|
end
|
46
53
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Effective
|
2
|
+
class Product < ActiveRecord::Base
|
3
|
+
self.table_name = EffectiveOrders.products_table_name.to_s
|
4
|
+
|
5
|
+
acts_as_purchasable
|
6
|
+
|
7
|
+
# structure do
|
8
|
+
# title :string
|
9
|
+
# price :integer, default: 0
|
10
|
+
# tax_exempt :boolean, default: false
|
11
|
+
#
|
12
|
+
# timestamps
|
13
|
+
# end
|
14
|
+
|
15
|
+
validates :title, presence: true
|
16
|
+
validates :price, numericality: { greater_than: 0 }
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
self[:title] || 'New Product'
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# https://www.ccbill.com/cs/wiki/tiki-index.php?page=Background+Post
|
2
|
+
class Effective::Providers::CcbillPostback
|
3
|
+
attr_reader :params
|
4
|
+
|
5
|
+
def initialize(params)
|
6
|
+
@params = params
|
7
|
+
end
|
8
|
+
|
9
|
+
def verified?
|
10
|
+
params[:responseDigest] == digest(digest_value)
|
11
|
+
end
|
12
|
+
|
13
|
+
def matches?(order)
|
14
|
+
price == order.total && order_id == order.to_param
|
15
|
+
end
|
16
|
+
|
17
|
+
def approval?
|
18
|
+
!denial?
|
19
|
+
end
|
20
|
+
|
21
|
+
def denial?
|
22
|
+
# denialId is for subscriptions only
|
23
|
+
[:reasonForDeclineCode, :reasonForDecline, :denialId].any? {|key| params[key].present?}
|
24
|
+
end
|
25
|
+
|
26
|
+
def order_details
|
27
|
+
@order_details ||= get_order_details
|
28
|
+
end
|
29
|
+
|
30
|
+
def order_id
|
31
|
+
params[:order_id]
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# https://www.ccbill.com/cs/wiki/tiki-index.php?page=Dynamic+Pricing+User+Guide#Postback
|
37
|
+
def digest_value
|
38
|
+
if approval?
|
39
|
+
"#{params[:subscription_id]}1#{salt}" # the `subscriptionId` param in the linked docs is a typo
|
40
|
+
else
|
41
|
+
"#{params[:denialId]}0#{salt}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def digest(value)
|
46
|
+
Digest::MD5.hexdigest(value)
|
47
|
+
end
|
48
|
+
|
49
|
+
def salt
|
50
|
+
EffectiveOrders.ccbill[:dynamic_pricing_salt]
|
51
|
+
end
|
52
|
+
|
53
|
+
# in cents
|
54
|
+
def price
|
55
|
+
return @price if @price.present?
|
56
|
+
formatted_price = params[:initialFormattedPrice] # example: "$10.00"
|
57
|
+
formatted_price = Nokogiri::HTML::DocumentFragment.parse(formatted_price).to_s # => "$10.00"
|
58
|
+
match = formatted_price.match(/^\D(\d*.\d\d)$/) # {a currency symbol}(digits.two digits)
|
59
|
+
return false unless match.present?
|
60
|
+
formatted_price = match[1] # => "10.00"
|
61
|
+
@price = formatted_price.sub('.', '').to_i # => 1000
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_order_details
|
65
|
+
# ignore some params
|
66
|
+
keepable = params.except(*ignorable_params)
|
67
|
+
# remove blanks
|
68
|
+
keepable.inject({}) do |details, kv_pair|
|
69
|
+
details[kv_pair[0]] = kv_pair[1] if kv_pair[1].present?
|
70
|
+
details
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def ignorable_params
|
75
|
+
[
|
76
|
+
# we have these already
|
77
|
+
:clientAccnum,
|
78
|
+
:clientSubacc,
|
79
|
+
:productDesc,
|
80
|
+
# a hash of billing information which CCBill doesn't share the format of (afaik)
|
81
|
+
:paymentAccount
|
82
|
+
]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
@@ -8,21 +8,25 @@ module Effective
|
|
8
8
|
|
9
9
|
belongs_to :customer
|
10
10
|
|
11
|
-
structure do
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
11
|
+
# structure do
|
12
|
+
# stripe_plan_id :string # This will be 'Weekly' or something like that
|
13
|
+
# stripe_subscription_id :string
|
14
|
+
# stripe_coupon_id :string
|
15
|
+
#
|
16
|
+
# title :string
|
17
|
+
# price :integer, default: 0
|
18
|
+
#
|
19
|
+
# timestamps
|
20
|
+
# end
|
21
21
|
|
22
22
|
delegate :user, :user_id, :to => :customer
|
23
23
|
|
24
|
-
|
25
|
-
|
24
|
+
validates :stripe_plan_id, presence: true
|
25
|
+
validates :title, presence: true
|
26
|
+
validates :price, numericality: { greater_than: 0 }
|
27
|
+
|
28
|
+
validates :customer, presence: true
|
29
|
+
validates :customer_id, uniqueness: { scope: [:stripe_plan_id] } # Can only be on each plan once.
|
26
30
|
|
27
31
|
before_validation do
|
28
32
|
self.errors.add(:stripe_plan_id, "is an invalid Plan") if stripe_plan_id.present? && stripe_plan.blank?
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Effective
|
2
|
+
class TaxRateCalculator
|
3
|
+
attr_reader :order
|
4
|
+
|
5
|
+
RATES = {
|
6
|
+
'CA' => { # Canada
|
7
|
+
'AB' => 5.00, # Alberta
|
8
|
+
'BC' => 5.00, # British Columbia
|
9
|
+
'MB' => 5.00, # Manitoba
|
10
|
+
'NB' => 13.0, # New Brunswick
|
11
|
+
'NL' => 13.0, # Newfoundland and Labrador
|
12
|
+
'NT' => 5.00, # Northwest Territories
|
13
|
+
'NS' => 15.0, # Nova Scotia
|
14
|
+
'ON' => 13.0, # Ontario
|
15
|
+
'PE' => 14.0, # Prince Edward Island
|
16
|
+
'QC' => 5.00, # Quebec
|
17
|
+
'SK' => 5.00, # Saskatchewan
|
18
|
+
'YT' => 5.00, # Yukon Territory
|
19
|
+
'NU' => 5.00 # Nunavut
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
def initialize(order:)
|
24
|
+
@order = order
|
25
|
+
end
|
26
|
+
|
27
|
+
def tax_rate
|
28
|
+
return nil unless order.billing_address.try(:country_code).present?
|
29
|
+
|
30
|
+
country = order.billing_address.country_code
|
31
|
+
state = order.billing_address.state_code
|
32
|
+
|
33
|
+
rate = RATES[country]
|
34
|
+
return rate if rate.kind_of?(Numeric)
|
35
|
+
return unknown_tax_rate() if rate.nil?
|
36
|
+
|
37
|
+
rate[state].presence || unknown_tax_rate()
|
38
|
+
end
|
39
|
+
|
40
|
+
def unknown_tax_rate
|
41
|
+
order.skip_buyer_validations? ? nil : 0
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -1,12 +1,9 @@
|
|
1
|
-
%h2.effective-orders-page-title Customers
|
1
|
+
%h2.effective-orders-page-title= (@page_title || 'Customers')
|
2
2
|
|
3
3
|
%p.text-right= link_to 'Stripe Dashboard: Customers', 'https://manage.stripe.com/customers', :class => 'btn btn-primary'
|
4
4
|
|
5
5
|
- if @datatable.nil?
|
6
|
-
%p
|
7
|
-
Please install
|
8
|
-
= link_to 'effective_datatables', 'https://github.com/code-and-effect/effective_datatables'
|
9
|
-
to see this page.
|
6
|
+
%p Please install #{link_to 'effective_datatables', 'https://github.com/code-and-effect/effective_datatables'} to see this page.
|
10
7
|
- elsif @datatable.present?
|
11
8
|
= render_datatable @datatable
|
12
9
|
- else
|
@@ -1,10 +1,7 @@
|
|
1
|
-
%h2.effective-orders-page-title Order Items
|
1
|
+
%h2.effective-orders-page-title= (@page_title || 'Order Items')
|
2
2
|
|
3
3
|
- if @datatable.nil?
|
4
|
-
%p
|
5
|
-
Please install
|
6
|
-
= link_to 'effective_datatables', 'https://github.com/code-and-effect/effective_datatables'
|
7
|
-
to see this page.
|
4
|
+
%p Please install #{link_to 'effective_datatables', 'https://github.com/code-and-effect/effective_datatables'} to see this page.
|
8
5
|
- elsif @datatable.present?
|
9
6
|
= render_datatable @datatable
|
10
7
|
- else
|
@@ -0,0 +1,28 @@
|
|
1
|
+
- unless defined?(Cocoon)
|
2
|
+
Please install #{link_to 'cocoon', 'https://github.com/nathanvda/cocoon'} to see this page.
|
3
|
+
- else
|
4
|
+
= simple_form_for [:admin, order], (EffectiveOrders.admin_simple_form_options || {}).merge(url: effective_orders.admin_orders_path) do |f|
|
5
|
+
= f.association :user,
|
6
|
+
label: 'Buyer',
|
7
|
+
required: true,
|
8
|
+
as: (defined?(EffectiveFormInputs) ? :effective_select : :select),
|
9
|
+
collection: @users || User.all.to_a.sort { |user1, user2| user1.to_s <=> user2.to_s }
|
10
|
+
|
11
|
+
%h3 Order Items
|
12
|
+
.order_items
|
13
|
+
- f.object.order_items.build unless f.object.order_items.present?
|
14
|
+
= f.simple_fields_for :order_items do |order_item|
|
15
|
+
= render 'order_item_fields', f: order_item
|
16
|
+
|
17
|
+
.links
|
18
|
+
= link_to_add_association '+ Add line item', f, :order_items, partial: 'order_item_fields'
|
19
|
+
|
20
|
+
= f.input :send_payment_request_to_buyer,
|
21
|
+
as: :boolean,
|
22
|
+
label: 'Yes, send a payment request email to the buyer.',
|
23
|
+
value: (f.object.send_payment_request_to_buyer.nil? ? EffectiveOrders.mailer[:send_payment_request_to_buyer] : f.object.send_payment_request_to_buyer?)
|
24
|
+
|
25
|
+
.form-group.pull-right
|
26
|
+
= f.button :submit, 'Save', data: { disable_with: 'Saving...' }
|
27
|
+
= f.button :submit, 'Save and Add New', data: { disable_with: 'Saving...' }
|
28
|
+
= link_to 'Cancel', effective_orders.admin_orders_path
|
@@ -0,0 +1,9 @@
|
|
1
|
+
.nested-fields.order-item
|
2
|
+
.row
|
3
|
+
- f.object.purchasable ||= Effective::Product.new
|
4
|
+
= f.simple_fields_for :purchasable do |purchasable|
|
5
|
+
.col-sm-2= f.input :quantity, input_html: { value: f.object.quantity || 1, min: 1 }
|
6
|
+
.col-sm-4= purchasable.input :title, input_html: { maxlength: 255 }
|
7
|
+
.col-sm-2= purchasable.input :price, as: (defined?(EffectiveFormInputs) ? :effective_price : :price)
|
8
|
+
.col-sm-2= purchasable.input :tax_exempt, label: 'Tax Exempt', input_html: { title: 'When checked, tax will not be applied to this item' }
|
9
|
+
.col-sm-2.remove-nested-fields= link_to_remove_association('Remove line item', f)
|
@@ -1,11 +1,15 @@
|
|
1
|
-
%h2.effective-orders-page-title Orders
|
1
|
+
%h2.effective-orders-page-title= (@page_title || 'Orders')
|
2
|
+
|
3
|
+
%p.text-right.effective-orders-page-action= link_to 'New Order', effective_orders.new_admin_order_path, :class => 'btn btn-primary'
|
2
4
|
|
3
5
|
- if @datatable.nil?
|
4
|
-
%p
|
5
|
-
Please install
|
6
|
-
= link_to 'effective_datatables', 'https://github.com/code-and-effect/effective_datatables'
|
7
|
-
to see this page.
|
6
|
+
%p Please install #{link_to 'effective_datatables', 'https://github.com/code-and-effect/effective_datatables'} to see this page.
|
8
7
|
- elsif @datatable.present?
|
9
8
|
= render_datatable @datatable
|
10
9
|
- else
|
11
10
|
%p There are no orders present
|
11
|
+
|
12
|
+
- if @datatable.present?
|
13
|
+
%p.text-right= link_to 'New Order', effective_orders.new_admin_order_path, :class => 'btn btn-primary'
|
14
|
+
|
15
|
+
|
@@ -19,19 +19,10 @@
|
|
19
19
|
- if cart.empty?
|
20
20
|
%tr
|
21
21
|
%td.quantity
|
22
|
-
%td.item
|
22
|
+
%td.item Your cart is empty.
|
23
23
|
%td.price
|
24
24
|
%tfoot
|
25
|
-
- if cart.tax > 0
|
26
|
-
%tr
|
27
|
-
%th.quantity
|
28
|
-
%th.subtotal Subtotal
|
29
|
-
%td.price.subtotal-price= price_to_currency(cart.subtotal)
|
30
|
-
%tr
|
31
|
-
%th.quantity
|
32
|
-
%th.tax Tax
|
33
|
-
%td.price.tax-price= price_to_currency(cart.tax)
|
34
25
|
%tr
|
35
26
|
%th.quantity
|
36
|
-
%th.
|
37
|
-
%td.price.
|
27
|
+
%th.subtotal Subtotal
|
28
|
+
%td.price.subtotal-price= price_to_currency(cart.subtotal)
|
@@ -1,20 +1,18 @@
|
|
1
|
-
%h2.effective-orders-page-title
|
1
|
+
%h2.effective-orders-page-title= (@page_title || 'My Cart')
|
2
2
|
|
3
3
|
- if @cart.empty?
|
4
4
|
%p Your cart is empty.
|
5
|
-
|
6
|
-
%hr
|
7
|
-
= link_to 'Home', root_url, :class => 'btn btn-primary'
|
8
|
-
- if EffectiveOrders.show_order_history_button
|
9
|
-
= link_to 'Order History', effective_orders.my_purchases_path, class: 'btn btn-default'
|
10
|
-
|
11
5
|
- else
|
12
6
|
%p Your cart has #{@cart.cart_items.length} items.
|
13
7
|
|
14
8
|
= render_cart(@cart)
|
15
|
-
|
16
9
|
%hr
|
17
|
-
=
|
18
|
-
|
19
|
-
|
20
|
-
|
10
|
+
= render partial: '/effective/carts/cart_actions', locals: { cart: @cart }
|
11
|
+
|
12
|
+
- if @pending_orders.present?
|
13
|
+
%h3 Pending Orders
|
14
|
+
%p The following orders are ready for you to purchase:
|
15
|
+
= render_orders_table(@pending_orders)
|
16
|
+
|
17
|
+
- if EffectiveOrders.show_order_history_button
|
18
|
+
= link_to_my_purchases(label: 'Order History')
|
@@ -0,0 +1,46 @@
|
|
1
|
+
.effective-order
|
2
|
+
= simple_form_for(order, (EffectiveOrders.simple_form_options || {}).merge(url: (order.new_record? ? effective_orders.orders_path : effective_orders.order_path(order)))) do |f|
|
3
|
+
= render partial: 'effective/orders/order_items', locals: {order: order, form: f}
|
4
|
+
|
5
|
+
- if order.errors[:order_items].present?
|
6
|
+
%p.inline-errors= order.errors[:order_items].first
|
7
|
+
|
8
|
+
- if order.errors[:total].present?
|
9
|
+
%p.inline-errors= order.errors[:total].first.gsub(EffectiveOrders.minimum_charge.to_i.to_s, price_to_currency(EffectiveOrders.minimum_charge.to_i))
|
10
|
+
|
11
|
+
- if EffectiveOrders.collect_user_fields.present? && (f.object.user rescue nil).present?
|
12
|
+
= render partial: 'effective/orders/order_user_fields', locals: {form: f, user: f.object.user }
|
13
|
+
|
14
|
+
- num_addresses = [EffectiveOrders.require_billing_address, EffectiveOrders.require_shipping_address].count(true)
|
15
|
+
|
16
|
+
- if num_addresses > 0
|
17
|
+
.row
|
18
|
+
- if EffectiveOrders.require_billing_address
|
19
|
+
%div{class: "col-sm-#{12 / num_addresses}"}
|
20
|
+
%h3 Billing Address
|
21
|
+
= effective_address_fields(f, :billing_address)
|
22
|
+
- if f.object.user.respond_to?(:billing_address=)
|
23
|
+
= f.input :save_billing_address, as: :boolean, label: 'Save as my default billing address', required: false
|
24
|
+
|
25
|
+
- if EffectiveOrders.require_shipping_address
|
26
|
+
%div{class: "col-sm-#{12 / num_addresses}"}
|
27
|
+
%h3 Shipping Address
|
28
|
+
- if EffectiveOrders.require_billing_address && EffectiveOrders.require_shipping_address
|
29
|
+
.shipping_address_fields{style: (f.object.shipping_address_same_as_billing? && (f.object.errors[:shipping_address] || []).blank?) ? 'display: none;' : 'display: block;'}
|
30
|
+
= effective_address_fields(f, :shipping_address)
|
31
|
+
- if f.object.user.respond_to?(:shipping_address=)
|
32
|
+
= f.input :save_shipping_address, as: :boolean, label: 'Save as my default shipping address', required: false
|
33
|
+
|
34
|
+
= f.input :shipping_address_same_as_billing, as: :boolean, label: 'My shipping address is the same as my billing address', required: false
|
35
|
+
|
36
|
+
- if EffectiveOrders.collect_note
|
37
|
+
= render partial: 'effective/orders/order_note_fields', locals: {form: f}
|
38
|
+
|
39
|
+
- unless f.object.pending? || current_cart.try(:empty?)
|
40
|
+
= link_to_current_cart(label: 'Change Items')
|
41
|
+
|
42
|
+
.pull-right
|
43
|
+
- if order.total == 0 && EffectiveOrders.allow_free_orders
|
44
|
+
= f.submit order_checkout_label(:free), class: 'btn btn-primary', rel: :nofollow, data: {'disable_with' => 'Processing...' }
|
45
|
+
- else
|
46
|
+
= f.submit 'Save and Continue', class: 'btn btn-primary', rel: :nofollow, data: {'disable_with' => 'Saving...' }
|