caboose-cms 0.5.69 → 0.5.70

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +8 -8
  2. data/app/assets/javascripts/caboose/admin.js +2 -1
  3. data/app/assets/javascripts/caboose/admin_edit_order.js +0 -13
  4. data/app/assets/javascripts/caboose/admin_main.js +13 -0
  5. data/app/assets/javascripts/caboose/cart.js +145 -161
  6. data/app/assets/javascripts/caboose/cart_old.js +176 -0
  7. data/app/assets/javascripts/caboose/checkout.js +1 -1
  8. data/app/assets/javascripts/caboose/{checkout_step2.js → checkout_addresses.js} +3 -3
  9. data/app/assets/javascripts/caboose/checkout_gift_cards.js +47 -0
  10. data/app/assets/javascripts/caboose/{checkout_step1.js → checkout_login_register.js} +5 -53
  11. data/app/assets/javascripts/caboose/checkout_module.js +3 -4
  12. data/app/assets/javascripts/caboose/{checkout_step4.js → checkout_payment.js} +8 -8
  13. data/app/assets/javascripts/caboose/{checkout_step3.js → checkout_shipping.js} +5 -5
  14. data/app/assets/javascripts/caboose/imageZoom.js +66 -0
  15. data/app/assets/javascripts/caboose/model/attribute.js +2 -1
  16. data/app/assets/javascripts/caboose/model/bound_select.js +15 -6
  17. data/app/assets/javascripts/caboose/product.js +12 -2
  18. data/app/assets/stylesheets/caboose/checkout.css.scss +1 -0
  19. data/app/assets/templates/caboose/checkout/address.jst.ejs +1 -1
  20. data/app/controllers/caboose/cart_controller.rb +60 -8
  21. data/app/controllers/caboose/checkout_controller.rb +42 -71
  22. data/app/controllers/caboose/gift_cards_controller.rb +216 -0
  23. data/app/controllers/caboose/users_controller.rb +2 -2
  24. data/app/helpers/caboose/checkout_helper.rb +6 -5
  25. data/app/models/caboose/core_plugin.rb +2 -1
  26. data/app/models/caboose/discount.rb +8 -13
  27. data/app/models/caboose/gift_card.rb +49 -0
  28. data/app/models/caboose/order.rb +66 -46
  29. data/app/models/caboose/order_package.rb +11 -4
  30. data/app/models/caboose/order_package_calculator.rb +102 -0
  31. data/app/models/caboose/product_image.rb +10 -0
  32. data/app/models/caboose/schema.rb +38 -29
  33. data/app/models/caboose/shipping_calculator.rb +4 -2
  34. data/app/models/caboose/shipping_package.rb +7 -0
  35. data/app/views/caboose/cart/index.html.erb +12 -2
  36. data/app/views/caboose/checkout/#Untitled-1# +2 -0
  37. data/app/views/caboose/checkout/_cart.html.erb +45 -48
  38. data/app/views/caboose/checkout/_cart_old.html.erb +49 -0
  39. data/app/views/caboose/checkout/_confirm.html.erb +6 -4
  40. data/app/views/caboose/checkout/_confirm_table.html.erb +0 -0
  41. data/app/views/caboose/checkout/{step_two.html.erb → addresses.html.erb} +2 -2
  42. data/app/views/caboose/checkout/gift_cards.html.erb +35 -0
  43. data/app/views/caboose/checkout/index.html.erb +53 -42
  44. data/app/views/caboose/checkout/payment.html.erb +108 -75
  45. data/app/views/caboose/checkout/shipping.html.erb +62 -13
  46. data/app/views/caboose/gift_cards/admin_edit.html.erb +89 -0
  47. data/app/views/caboose/gift_cards/admin_index.html.erb +52 -0
  48. data/config/routes.rb +39 -19
  49. data/lib/caboose/engine.rb +1 -0
  50. data/lib/caboose/version.rb +1 -1
  51. metadata +20 -14
  52. data/app/assets/javascripts/caboose/cart2.js +0 -98
  53. data/app/views/caboose/checkout/step_four.html.erb +0 -67
  54. data/app/views/caboose/checkout/step_four_old.html.erb +0 -63
  55. data/app/views/caboose/checkout/step_one.html.erb +0 -54
  56. data/app/views/caboose/checkout/step_one_old.html.erb +0 -13
  57. data/app/views/caboose/checkout/step_three.html.erb +0 -55
  58. data/app/views/caboose/checkout/step_two_old.html.erb +0 -14
@@ -390,6 +390,7 @@
390
390
  }
391
391
 
392
392
  #checkout-confirm {
393
+ margin-top: 10px;
393
394
  width: 100%;
394
395
  #line-items { width: 100%; margin: 0 auto;
395
396
  table {
@@ -1,5 +1,5 @@
1
1
  <div class="wrapper">
2
- <form action="/checkout/address" method="put">
2
+ <form action="/checkout/addresses" method="put">
3
3
  <section>
4
4
  <fieldset id="shipping">
5
5
  <h3>Shipping Address</h3>
@@ -7,14 +7,29 @@ module Caboose
7
7
 
8
8
  # GET /cart/items
9
9
  def list
10
- render :json => @order.as_json(:include => [
11
- { :line_items => { :include => { :variant => { :include => :product }}}},
12
- { :order_packages => { :include => [:shipping_package, :shipping_method] }},
13
- :customer,
14
- :shipping_address,
15
- :billing_address,
16
- :order_transactions
17
- ])
10
+ render :json => @order.as_json(
11
+ :include => [
12
+ {
13
+ :line_items => {
14
+ :include => {
15
+ :variant => {
16
+ :include => [
17
+ { :product_images => { :methods => :urls }},
18
+ { :product => { :include => { :product_images => { :methods => :urls }}}}
19
+ ],
20
+ :methods => :title
21
+ }
22
+ }
23
+ }
24
+ },
25
+ { :order_packages => { :include => [:shipping_package, :shipping_method] }},
26
+ :customer,
27
+ :shipping_address,
28
+ :billing_address,
29
+ :order_transactions,
30
+ { :discounts => { :include => :gift_card }}
31
+ ]
32
+ )
18
33
  end
19
34
 
20
35
  # GET /cart/item-count
@@ -60,6 +75,43 @@ module Caboose
60
75
  li = LineItem.find(params[:line_item_id]).destroy
61
76
  render :json => { :success => true, :item_count => @order.line_items.count }
62
77
  end
78
+
79
+ # POST /cart/gift-cards
80
+ def add_gift_card
81
+ resp = StdClass.new
82
+ code = params[:code].strip
83
+ gc = GiftCard.where("lower(code) = ?", code.downcase).first
84
+
85
+ if gc.nil? then resp.error = "Invalid gift card code."
86
+ elsif gc.status != GiftCard::STATUS_ACTIVE then resp.error = "That gift card is not active."
87
+ elsif gc.date_available && DateTime.now.utc < self.date_available then resp.error = "That gift card is not active yet."
88
+ elsif gc.date_expires && DateTime.now.utc > self.date_expires then resp.error = "That gift card is expired."
89
+ elsif gc.card_type == GiftCard::CARD_TYPE_AMOUNT && gc.balance <= 0 then resp.error = "That gift card has a zero balance."
90
+ elsif gc.min_order_total && @order.total < gc.min_order_total then resp.error = "Your order must be at least $#{sprintf('%.2f',gc.min_order_total)} to use this gift card."
91
+ elsif Discount.where(:order_id => @order.id, :gift_card_id => gc.id).exists? then resp.error = "That gift card has already been applied to this order."
92
+ else
93
+ # Determine how much the discount will be
94
+ d = Discount.new(:order_id => @order.id, :gift_card_id => gc.id, :amount => 0.0)
95
+ case gc.card_type
96
+ when GiftCard::CARD_TYPE_AMOUNT then d.amount = (@order.total > gc.balance ? gc.balance : @order.total)
97
+ when GiftCard::CARD_TYPE_PERCENTAGE then d.amount = @order.subtotal * gc.total
98
+ when GiftCard::CARD_TYPE_NO_SHIPPING then d.amount = @order.shipping
99
+ when GiftCard::CARD_TYPE_NO_TAX then d.amount = @order.tax
100
+ end
101
+ d.save
102
+ @order.calculate
103
+ resp.success = true
104
+ resp.order_total = @order.total
105
+ end
106
+ render :json => resp
107
+ end
108
+
109
+ # DELETE /cart/discounts/:discount_id
110
+ def remove_discount
111
+ Discount.find(params[:discount_id]).destroy
112
+ @order.calculate
113
+ render :json => { :success => true }
114
+ end
63
115
  end
64
116
  end
65
117
 
@@ -10,52 +10,57 @@ module Caboose
10
10
  redirect_to '/checkout/empty' if @order.line_items.empty?
11
11
  end
12
12
 
13
+ # Step 1 - Login or register
13
14
  # GET /checkout
14
- def index
15
- redirect_to '/checkout/step-one'
16
- end
17
-
18
- # GET /checkout/step-one
19
- def step_one
15
+ def index
20
16
  if logged_in?
21
17
  if @order.customer_id.nil?
22
18
  @order.customer_id = logged_in_user.id
23
19
  @order.save
24
20
  end
25
- redirect_to '/checkout/step-two'
21
+ redirect_to '/checkout/addresses'
26
22
  return
27
23
  end
28
24
  end
29
25
 
30
- # GET /checkout/step-two
31
- def step_two
32
- #redirect_to '/checkout/step-one' if !@order.shipping_address || !@order.billing_address
33
- redirect_to '/checkout/step-one' if !logged_in?
26
+ # Step 2 - Shipping and billing addresses
27
+ # GET /checkout/addresses
28
+ def addresses
29
+ redirect_to '/checkout' if !logged_in?
34
30
  end
35
31
 
36
- # GET /checkout/step-three
37
- def step_three
38
- redirect_to '/checkout/step-one' and return if !logged_in?
39
- redirect_to '/checkout/step-two' and return if @order.shipping_address.nil? || @order.billing_address.nil?
40
-
32
+ # Step 3 - Shipping method
33
+ # GET /checkout/shipping
34
+ def shipping
35
+ redirect_to '/checkout' and return if !logged_in?
36
+ redirect_to '/checkout/addresses' and return if @order.shipping_address.nil? || @order.billing_address.nil?
37
+
41
38
  # Remove any order packages
42
39
  LineItem.where(:order_id => @order.id).update_all(:order_package_id => nil)
43
40
  OrderPackage.where(:order_id => @order.id).destroy_all
44
-
41
+
45
42
  # Calculate what shipping packages we'll need
46
43
  OrderPackage.create_for_order(@order)
47
44
 
48
- # Now get the rates for those packages
49
- Caboose.log("Getting rates...")
45
+ # Now get the rates for those packages
50
46
  @rates = ShippingCalculator.rates(@order)
51
47
  Caboose.log(@rates.inspect)
52
48
  end
53
49
 
54
- # GET /checkout/step-four
55
- def step_four
56
- redirect_to '/checkout/step-one' and return if !logged_in?
57
- redirect_to '/checkout/step-two' and return if @order.shipping_address.nil? || @order.billing_address.nil?
58
- redirect_to '/checkout/step-three' and return if @order.shipping_service_code.nil?
50
+ # Step 4 - Gift cards
51
+ # GET /checkout/gift-cards
52
+ def gift_cards
53
+ redirect_to '/checkout' and return if !logged_in?
54
+ redirect_to '/checkout/addresses' and return if @order.shipping_address.nil? || @order.billing_address.nil?
55
+ redirect_to '/checkout/shipping' and return if @order.shipping_service_code.nil?
56
+ end
57
+
58
+ # Step 5 - Payment
59
+ # GET /checkout/payment
60
+ def payment
61
+ redirect_to '/checkout' and return if !logged_in?
62
+ redirect_to '/checkout/addresses' and return if @order.shipping_address.nil? || @order.billing_address.nil?
63
+ redirect_to '/checkout/shipping' and return if @order.shipping_service_code.nil?
59
64
 
60
65
  # Make sure all the variants still exist
61
66
  @order.line_items.each do |li|
@@ -103,8 +108,8 @@ module Caboose
103
108
  }
104
109
  end
105
110
 
106
- # PUT /checkout/address
107
- def update_address
111
+ # PUT /checkout/addresses
112
+ def update_addresses
108
113
 
109
114
  # Grab or create addresses
110
115
  shipping_address = if @order.shipping_address then @order.shipping_address else Address.new end
@@ -177,7 +182,7 @@ module Caboose
177
182
  resp.errors = @order.errors.full_messages
178
183
  else
179
184
  @order.save
180
- resp.redirect = '/checkout/step-two'
185
+ resp.redirect = '/checkout/addresses'
181
186
  end
182
187
  end
183
188
  render :json => resp
@@ -190,29 +195,13 @@ module Caboose
190
195
 
191
196
  # PUT /checkout/shipping
192
197
  def update_shipping
193
-
194
- rates = ShippingCalculator.rates(@order)
195
-
196
- if @site.store_config.calculate_packages
197
- # TODO: Add the separate shipping costs for each package
198
- else
199
- @order.shipping_carrier = params[:carrier]
200
- @order.shipping_service_code = params[:service_code]
201
- @order.shipping_service_name = params[:service_name]
202
-
203
- rates[0][:rates].each do |rate|
204
- if rate[:carrier] == params[:carrier] && rate[:service_code] == params[:service_code]
205
- @order.shipping = rate[:total_price]
206
- break
207
- end
208
- end
209
- end
210
- render :json => {
211
- :success => @order.save,
212
- :errors => @order.errors.full_messages
213
- #:order => @order,
214
- #:selected_rate => ShippingCalculator.rate(@order)
215
- }
198
+ op = OrderPackage.find(params[:order_package_id])
199
+ op.shipping_method_id = params[:shipping_method_id]
200
+ op.total = params[:total]
201
+ op.save
202
+ op.order.calculate
203
+
204
+ render :json => { :success => true }
216
205
  end
217
206
 
218
207
  # GET /checkout/payment
@@ -254,6 +243,9 @@ module Caboose
254
243
  if ot.success
255
244
  order.financial_status = 'authorized'
256
245
  order.status = 'pending'
246
+
247
+ # Take funds from any gift cards that were used on the order
248
+ order.take_gift_card_funds
257
249
 
258
250
  # Send out emails
259
251
  OrdersMailer.configure_for_site(@site.id).customer_new_order(order).deliver
@@ -291,27 +283,6 @@ module Caboose
291
283
  render :layout => false
292
284
  end
293
285
 
294
- # GET /checkout/discount
295
- #def discount
296
- # # TODO make it possible to use multiple discounts
297
- #
298
- # @gift_card = @order.discounts.first
299
- #end
300
-
301
- # POST /checkout/update-discount
302
- #def add_discount
303
- # gift_card = Discount.find_by_code(params[:gift_card_number])
304
- #
305
- # render :json => { :error => true, :message => 'Gift card not found.' } and return if gift_card.nil?
306
- # render :json => { :error => true, :message => 'Gift card has no remaining funds.' } and return if gift_card.amount_current <= 0
307
- #
308
- # @order.discounts.delete_all if @order.discounts.any?
309
- # @order.discounts << gift_card
310
- # @order.calculate_total
311
- #
312
- # render :json => { :success => true, :message => 'Gift card added successfully.' }
313
- #end
314
-
315
286
  #def relay
316
287
  #
317
288
  # # Check to see that the order has a valid total and was authorized
@@ -0,0 +1,216 @@
1
+ module Caboose
2
+ class GiftCardsController < Caboose::ApplicationController
3
+
4
+ # GET /admin/gift-cards
5
+ def admin_index
6
+ return if !user_is_allowed('giftcards', 'view')
7
+ render :layout => 'caboose/admin'
8
+ end
9
+
10
+ # GET /admin/gift-cards/json
11
+ def admin_json
12
+ return if !user_is_allowed('giftcards', 'view')
13
+
14
+ pager = PageBarGenerator.new(params, {
15
+ 'site_id' => @site.id,
16
+ 'name' => '',
17
+ 'code' => '',
18
+ 'card_type' => '',
19
+ 'total_lte' => '',
20
+ 'total_gte' => '',
21
+ 'balance_lte' => '',
22
+ 'balance_gte' => '',
23
+ 'min_order_total_lte' => '',
24
+ 'min_order_total_gte' => '',
25
+ 'date_available_lte' => '',
26
+ 'date_available_gte' => '',
27
+ 'date_expires_lte' => '',
28
+ 'date_expires_gte' => '',
29
+ 'status' => ''
30
+ },{
31
+ 'model' => 'Caboose::GiftCard',
32
+ 'sort' => 'code',
33
+ 'desc' => false,
34
+ 'base_url' => "/admin/gift-cards",
35
+ 'use_url_params' => false
36
+ })
37
+ render :json => {
38
+ :pages => pager,
39
+ :models => pager.items
40
+ }
41
+ end
42
+
43
+ # GET /admin/gift-cards/:id/json
44
+ def admin_json_single
45
+ return if !user_is_allowed('giftcards', 'view')
46
+ gc = GiftCard.find(params[:id])
47
+ render :json => gc
48
+ end
49
+
50
+ # GET /admin/gift-cards/new
51
+ def admin_new
52
+ return if !user_is_allowed('giftcards', 'add')
53
+ render :layout => 'caboose/admin'
54
+ end
55
+
56
+ # POST /admin/gift-cards
57
+ def admin_add
58
+ return if !user_is_allowed('giftcards', 'add')
59
+
60
+ resp = StdClass.new
61
+ code = params[:code].strip
62
+
63
+ if code.length == 0
64
+ resp.error = "A valid code is required."
65
+ elsif GiftCard.where(:code => code).exists?
66
+ resp.error = "A gift card with that code already exists."
67
+ else
68
+ gc = GiftCard.new(
69
+ :site_id => @site.id,
70
+ :code => code,
71
+ :status => GiftCard::STATUS_INACTIVE
72
+ )
73
+ resp.success = gc.save
74
+ resp.new_id = gc.id
75
+ resp.redirect = "/admin/gift-cards/#{gc.id}"
76
+ end
77
+
78
+ render :json => resp
79
+ end
80
+
81
+ # POST /admin/gift-cards/bulk
82
+ def admin_bulk_add
83
+ return if !user_is_allowed('sites', 'add')
84
+
85
+ resp = Caboose::StdClass.new
86
+ i = 0
87
+ CSV.parse(params[:csv_data].strip).each do |row|
88
+ if row[0].nil? || row[0].strip.length == 0
89
+ resp.error = "Code not defined on row #{i+1}."
90
+ end
91
+ i = i + 1
92
+ end
93
+
94
+ if resp.error.nil?
95
+ CSV.parse(params[:csv_data]).each do |row|
96
+ Caboose::GiftCard.create(
97
+ :site_id => @site.id,
98
+ :code => row[0].strip,
99
+ :status => GiftCard::STATUS_INACTIVE
100
+ )
101
+ end
102
+ resp.success = true
103
+ end
104
+
105
+ render :json => resp
106
+ end
107
+
108
+ # GET /admin/gift-cards/:id
109
+ def admin_edit
110
+ return if !user_is_allowed('giftcards', 'edit')
111
+ @gift_card = GiftCard.find(params[:id])
112
+ render :layout => 'caboose/admin'
113
+ end
114
+
115
+ # PUT /admin/gift-cards/:id
116
+ def admin_update
117
+ return if !user_is_allowed('giftcards', 'edit')
118
+
119
+ resp = Caboose::StdClass.new
120
+ gc = GiftCard.find(params[:id])
121
+
122
+ save = true
123
+ params.each do |name,value|
124
+ case name
125
+ when 'site_id' then gc.site_id = value
126
+ when 'name' then gc.name = value
127
+ when 'code' then gc.code = value
128
+ when 'card_type' then gc.card_type = value
129
+ when 'total' then gc.total = value
130
+ when 'balance' then gc.balance = value
131
+ when 'min_order_total' then gc.min_order_total = value
132
+ when 'date_available' then gc.date_available = DateTime.strptime(value, '%m/%d/%Y')
133
+ when 'date_expires' then gc.date_expires = DateTime.strptime(value, '%m/%d/%Y')
134
+ when 'status' then gc.status = value
135
+ end
136
+ end
137
+ resp.success = save && gc.save
138
+ render :json => resp
139
+ end
140
+
141
+ # PUT /admin/gift-cards/bulk
142
+ def admin_bulk_update
143
+ return unless user_is_allowed_to 'edit', 'sites'
144
+
145
+ resp = Caboose::StdClass.new
146
+ gift_cards = params[:model_ids].collect{ |gc_id| GiftCard.find(gc_id) }
147
+
148
+ save = true
149
+ params.each do |k,v|
150
+ case k
151
+ when 'site_id' then gift_cards.each{ |gc| gc.site_id = v }
152
+ when 'name' then gift_cards.each{ |gc| gc.name = v }
153
+ when 'code' then gift_cards.each{ |gc| gc.code = v }
154
+ when 'card_type' then gift_cards.each{ |gc| gc.card_type = v }
155
+ when 'total' then gift_cards.each{ |gc| gc.total = v }
156
+ when 'balance' then gift_cards.each{ |gc| gc.balance = v }
157
+ when 'min_order_total' then gift_cards.each{ |gc| gc.min_order_total = v }
158
+ when 'date_available' then gift_cards.each{ |gc| gc.date_available = DateTime.strptime(v, '%m/%d/%Y') }
159
+ when 'date_expires' then gift_cards.each{ |gc| gc.date_expires = DateTime.strptime(v, '%m/%d/%Y') }
160
+ when 'status' then gift_cards.each{ |gc| gc.status = v }
161
+ end
162
+ end
163
+ gift_cards.each{ |gc| gc.save }
164
+
165
+ resp.success = true
166
+ render :json => resp
167
+ end
168
+
169
+ # DELETE /admin/gift-cards/:id
170
+ def admin_delete
171
+ return if !user_is_allowed('giftcards', 'delete')
172
+ GiftCard.find(params[:id]).destroy
173
+ render :json => Caboose::StdClass.new({
174
+ :redirect => '/admin/gift-cards'
175
+ })
176
+ end
177
+
178
+ # DELETE /admin/gift-cards/:id/bulk
179
+ def admin_bulk_delete
180
+ return if !user_is_allowed('sites', 'delete')
181
+
182
+ resp = Caboose::StdClass.new
183
+ params[:model_ids].each do |gc_id|
184
+ GiftCard.find(gc_id).destroy
185
+ end
186
+ resp.success = true
187
+ render :json => resp
188
+ end
189
+
190
+ # GET /admin/gift-cards/status-options
191
+ def admin_status_options
192
+ return if !user_is_allowed('categories', 'view')
193
+ statuses = [
194
+ GiftCard::STATUS_INACTIVE,
195
+ GiftCard::STATUS_ACTIVE,
196
+ GiftCard::STATUS_EXPIRED
197
+ ]
198
+ options = statuses.collect{ |s| { 'text' => s, 'value' => s }}
199
+ render :json => options
200
+ end
201
+
202
+ # GET /admin/gift-cards/card-type-options
203
+ def admin_card_type_options
204
+ return if !user_is_allowed('categories', 'view')
205
+ types = [
206
+ GiftCard::CARD_TYPE_AMOUNT,
207
+ GiftCard::CARD_TYPE_PERCENTAGE,
208
+ GiftCard::CARD_TYPE_NO_SHIPPING,
209
+ GiftCard::CARD_TYPE_NO_TAX,
210
+ ]
211
+ options = types.collect{ |s| { 'text' => s, 'value' => s }}
212
+ render :json => options
213
+ end
214
+
215
+ end
216
+ end