caboose-cms 0.5.122 → 0.5.123

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.
Files changed (50) hide show
  1. checksums.yaml +8 -8
  2. data/app/assets/javascripts/caboose/admin.js +1 -0
  3. data/app/assets/javascripts/caboose/admin_edit_order.js +6 -8
  4. data/app/assets/javascripts/caboose/cart.js +2 -2
  5. data/app/assets/javascripts/caboose/jquery.datetimepicker.js +1925 -0
  6. data/app/assets/javascripts/caboose/model/all.js +1 -0
  7. data/app/assets/javascripts/caboose/model/bound_date.js +10 -3
  8. data/app/assets/javascripts/caboose/model/bound_date_time.js +121 -0
  9. data/app/assets/javascripts/caboose/model/model_binder.js +3 -0
  10. data/app/assets/stylesheets/caboose/admin.css +1 -0
  11. data/app/assets/stylesheets/caboose/jquery.datetimepicker.css +523 -0
  12. data/app/assets/templates/caboose/cart/line_items.jst.ejs +1 -1
  13. data/app/assets/templates/caboose/checkout/line_items.jst.ejs +2 -2
  14. data/app/controllers/caboose/checkout_controller.rb +3 -2
  15. data/app/controllers/caboose/line_items_controller.rb +4 -2
  16. data/app/controllers/caboose/my_account_controller.rb +43 -0
  17. data/app/controllers/caboose/my_account_orders_controller.rb +40 -6
  18. data/app/controllers/caboose/orders_controller.rb +26 -20
  19. data/app/controllers/caboose/products_controller.rb +1 -0
  20. data/app/controllers/caboose/sites_controller.rb +15 -1
  21. data/app/controllers/caboose/users_controller.rb +0 -35
  22. data/app/controllers/caboose/variants_controller.rb +51 -2
  23. data/app/controllers/caboose/vendors_controller.rb +3 -2
  24. data/app/models/caboose/address.rb +9 -1
  25. data/app/models/caboose/line_item.rb +17 -9
  26. data/app/models/caboose/model_binder.rb +63 -0
  27. data/app/models/caboose/order.rb +21 -14
  28. data/app/models/caboose/order_pdf.rb +3 -3
  29. data/app/models/caboose/pending_orders_pdf.rb +1 -1
  30. data/app/models/caboose/product.rb +15 -16
  31. data/app/models/caboose/schema.rb +20 -13
  32. data/app/models/caboose/site.rb +9 -0
  33. data/app/models/caboose/store_config.rb +6 -0
  34. data/app/models/caboose/variant.rb +15 -1
  35. data/app/views/caboose/checkout/_cart.html.erb +3 -3
  36. data/app/views/caboose/checkout/_confirm.html.erb +3 -3
  37. data/app/views/caboose/login/index.html.erb +7 -3
  38. data/app/views/caboose/{users/my_account.html.erb → my_account/index.html.erb} +7 -6
  39. data/app/views/caboose/my_account_orders/edit.html.erb +104 -0
  40. data/app/views/caboose/my_account_orders/index.html.erb +36 -0
  41. data/app/views/caboose/sites/admin_edit.html.erb +2 -0
  42. data/app/views/caboose/variants/admin_edit.html.erb +11 -1
  43. data/app/views/caboose/variants/admin_index.html.erb +5 -2
  44. data/config/routes.rb +7 -2
  45. data/lib/caboose/#Untitled-1# +264 -0
  46. data/lib/caboose/engine.rb +23 -140
  47. data/lib/caboose/version.rb +1 -1
  48. data/lib/tasks/caboose.rake +15 -1
  49. metadata +11 -4
  50. data/app/views/caboose/orders/admin_edit_old.html.erb +0 -155
@@ -26,7 +26,7 @@
26
26
  </section>
27
27
 
28
28
  <section>
29
- <p class="price">$<%= parseFloat(Math.round(lineItem.price * 100) / 100).toFixed(2) %></p>
29
+ <p class="price">$<%= parseFloat(Math.round(lineItem.subtotal * 100) / 100).toFixed(2) %></p>
30
30
  </section>
31
31
  </li>
32
32
  <% }); %>
@@ -6,10 +6,10 @@
6
6
  <div class="wrapper">
7
7
  <aside>
8
8
  <figure style="background-image: url(<%= lineItem.variant.images[0].urls.thumb %>)"></figure>
9
- <p><%= lineItem.title %><br />Qty: <%= lineItem.quantity %><br /><span class="price">$<%= ((parseFloat(lineItem.price) * 100) / 100).toFixed(2) %></span></p>
9
+ <p><%= lineItem.title %><br />Qty: <%= lineItem.quantity %><br /><span class="price">$<%= ((parseFloat(lineItem.unit_price) * 100) / 100).toFixed(2) %></span></p>
10
10
  </aside>
11
11
  <section>
12
- <p>$<%= ((parseFloat(lineItem.price) * 100) / 100).toFixed(2) %></p>
12
+ <p>$<%= ((parseFloat(lineItem.subtotal) * 100) / 100).toFixed(2) %></p>
13
13
  </section>
14
14
  </div>
15
15
  </li>
@@ -257,8 +257,9 @@ module Caboose
257
257
 
258
258
  error = nil
259
259
  if ot.success
260
- order.financial_status = 'authorized'
261
- order.status = 'pending'
260
+ order.financial_status = Order::FINANCIAL_STATUS_AUTHORIZED
261
+ order.status = Order::STATUS_PENDING
262
+ order.order_number = @site.store_config.next_order_number
262
263
 
263
264
  # Take funds from any gift cards that were used on the order
264
265
  order.take_gift_card_funds
@@ -24,7 +24,8 @@ module Caboose
24
24
  :order_id => params[:order_id],
25
25
  :variant_id => params[:variant_id],
26
26
  :quantity => 1,
27
- :price => v.price,
27
+ :unit_price => v.price,
28
+ :subtotal => v.price,
28
29
  :status => 'pending'
29
30
  )
30
31
  resp.success = li.save
@@ -46,7 +47,8 @@ module Caboose
46
47
  when 'order_package_id' then li.order_package_id = value
47
48
  when 'variant_id' then li.variant_id = value
48
49
  when 'parent_id' then li.parent_id = value
49
- when 'price' then li.price = value
50
+ when 'unit_price' then li.unit_price = value
51
+ when 'subtotal' then li.subtotal = value
50
52
  when 'notes' then li.notes = value
51
53
  when 'custom1' then li.custom1 = value
52
54
  when 'custom2' then li.custom2 = value
@@ -0,0 +1,43 @@
1
+ module Caboose
2
+ class MyAccountController < Caboose::ApplicationController
3
+
4
+ # GET /my-account
5
+ def index
6
+ return if !verify_logged_in
7
+ @user = logged_in_user
8
+ end
9
+
10
+ # PUT /my-account
11
+ def update
12
+ return if !logged_in?
13
+
14
+ resp = StdClass.new
15
+ user = logged_in_user
16
+
17
+ save = true
18
+ params.each do |name,value|
19
+ case name
20
+ when "first_name" then user.first_name = value
21
+ when "last_name" then user.last_name = value
22
+ when "username" then user.username = value
23
+ when "email" then user.email = value
24
+ when "phone" then user.phone = value
25
+ when "password"
26
+ confirm = params[:confirm]
27
+ if value != confirm
28
+ resp.error = "Passwords do not match.";
29
+ save = false
30
+ elsif value.length < 8
31
+ resp.error = "Passwords must be at least 8 characters.";
32
+ save = false
33
+ else
34
+ user.password = Digest::SHA1.hexdigest(Caboose::salt + value)
35
+ end
36
+ end
37
+ end
38
+
39
+ resp.success = save && user.save
40
+ render :json => resp
41
+ end
42
+ end
43
+ end
@@ -6,17 +6,16 @@ module Caboose
6
6
  return if !logged_in?
7
7
 
8
8
  @pager = Caboose::PageBarGenerator.new(params, {
9
- 'customer_id' => @logged_in_user_id.id,
10
- 'status' => '',
11
- 'id' => ''
9
+ 'customer_id' => logged_in_user.id,
10
+ 'status' => [Order::STATUS_PENDING, Order::STATUS_CANCELED, Order::STATUS_SHIPPED]
12
11
  }, {
13
12
  'model' => 'Caboose::Order',
14
- 'sort' => 'id',
13
+ 'sort' => 'order_number',
15
14
  'desc' => 1,
16
15
  'base_url' => '/my-account/orders',
17
16
  'use_url_params' => false
18
17
  })
19
- @orders = @pager.items
18
+ @orders = @pager.all_items
20
19
  end
21
20
 
22
21
  # GET /my-account/orders/:id
@@ -30,6 +29,41 @@ module Caboose
30
29
  return
31
30
  end
32
31
  end
33
-
32
+ # GET /my-account
33
+ def my_account
34
+ return if !logged_in?
35
+ @user = logged_in_user
36
+ render :layout => 'caboose/modal'
37
+ end
38
+
39
+ # PUT /my-account
40
+ def update_my_account
41
+ return if !logged_in?
42
+
43
+ resp = StdClass.new
44
+ user = logged_in_user
45
+
46
+ save = true
47
+ params.each do |name,value|
48
+ case name
49
+ when "first_name", "last_name", "username", "email", "phone"
50
+ user[name.to_sym] = value
51
+ when "password"
52
+ confirm = params[:confirm]
53
+ if (value != confirm)
54
+ resp.error = "Passwords do not match.";
55
+ save = false
56
+ elsif (value.length < 8)
57
+ resp.error = "Passwords must be at least 8 characters.";
58
+ save = false
59
+ else
60
+ user.password = Digest::SHA1.hexdigest(Caboose::salt + value)
61
+ end
62
+ end
63
+ end
64
+
65
+ resp.success = save && user.save
66
+ render json: resp
67
+ end
34
68
  end
35
69
  end
@@ -16,7 +16,7 @@ module Caboose
16
16
  @pager = Caboose::PageBarGenerator.new(params, {
17
17
  'site_id' => @site.id,
18
18
  'customer_id' => '',
19
- 'status' => 'pending',
19
+ 'status' => Order::STATUS_PENDING,
20
20
  'shipping_method_code' => '',
21
21
  'id' => ''
22
22
  }, {
@@ -43,8 +43,8 @@ module Caboose
43
43
  def admin_add
44
44
  return if !user_is_allowed('orders', 'add')
45
45
  order = Order.create(
46
- :status => 'pending',
47
- :financial_status => 'pending'
46
+ :status => Order::STATUS_PENDING,
47
+ :financial_status => Order::FINANCIAL_STATUS_PENDING
48
48
  )
49
49
  render :json => { :sucess => true, :redirect => "/admin/orders/#{order.id}" }
50
50
  end
@@ -64,7 +64,7 @@ module Caboose
64
64
  order = Order.find(params[:id])
65
65
  t = OrderTransaction.where(:order_id => order.id, :transaction_type => OrderTransaction::TYPE_AUTHORIZE, :success => true).first
66
66
 
67
- if order.financial_status == 'captured'
67
+ if order.financial_status == Order::FINANCIAL_STATUS_CAPTURED
68
68
  resp.error = "This order has already been captured, you will need to refund instead"
69
69
  elsif t.nil?
70
70
  resp.error = "This order doesn't seem to be authorized."
@@ -78,12 +78,12 @@ module Caboose
78
78
  sc.pp_username,
79
79
  sc.pp_password,
80
80
  order.total,
81
- :transaction_type => 'VOID',
81
+ :transaction_type => OrderTransaction::TYPE_VOID,
82
82
  :transaction_id => t.transaction_id
83
83
  )
84
84
  order.update_attributes(
85
- :financial_status => 'voided',
86
- :status => 'cancelled'
85
+ :financial_status => Order::FINANCIAL_STATUS_VOIDED,
86
+ :status => Order::STATUS_CANCELED
87
87
  )
88
88
  order.save
89
89
  # TODO: Add the variant quantities ordered back
@@ -109,13 +109,13 @@ module Caboose
109
109
 
110
110
  order = Order.find(params[:id])
111
111
 
112
- if order.financial_status != 'captured'
112
+ if order.financial_status != Order::FINANCIAL_STATUS_CAPTURED
113
113
  response.error = "This order hasn't been captured yet, you will need to void instead"
114
114
  else
115
115
  if PaymentProcessor.refund(order)
116
116
  order.update_attributes(
117
- :financial_status => 'refunded',
118
- :status => 'cancelled'
117
+ :financial_status => Order::FINANCIAL_STATUS_REFUNDED,
118
+ :status => Order::STATUS_CANCELED
119
119
  )
120
120
 
121
121
  response.success = 'Order refunded successfully'
@@ -214,7 +214,7 @@ module Caboose
214
214
  return if !user_is_allowed('orders', 'edit')
215
215
 
216
216
  pdf = PendingOrdersPdf.new
217
- pdf.orders = Order.where(:status => 'pending').all
217
+ pdf.orders = Order.where(:status => Order::STATUS_PENDING).all
218
218
  send_data pdf.to_pdf, :filename => "pending_orders.pdf", :type => "application/pdf", :disposition => "inline"
219
219
  end
220
220
 
@@ -258,7 +258,7 @@ module Caboose
258
258
  order = Order.find(params[:id])
259
259
  t = OrderTransaction.where(:order_id => order.id, :transaction_type => OrderTransaction::TYPE_AUTHORIZE, :success => true).first
260
260
 
261
- if order.financial_status == 'captured'
261
+ if order.financial_status == Order::FINANCIAL_STATUS_CAPTURED
262
262
  resp.error = "Funds for this order have already been captured."
263
263
  elsif order.total > order.auth_amount
264
264
  resp.error = "The order total exceeds the authorized amount."
@@ -277,7 +277,7 @@ module Caboose
277
277
  :transaction_type => 'CAPTURE_ONLY',
278
278
  :transaction_id => t.transaction_id
279
279
  )
280
- order.update_attribute(:financial_status, 'captured')
280
+ order.update_attribute(:financial_status, Order::FINANCIAL_STATUS_CAPTURED)
281
281
  resp.success = 'Captured funds successfully'
282
282
  when 'payscape'
283
283
  # TODO: Implement capture funds for payscape
@@ -372,9 +372,15 @@ module Caboose
372
372
 
373
373
  # GET /admin/orders/status-options
374
374
  def admin_status_options
375
- return if !user_is_allowed('categories', 'view')
376
- statuses = ['cart', 'pending', 'ready to ship', 'shipped', 'canceled']
377
- options = statuses.collect{ |s| { 'text' => s, 'value' => s }}
375
+ return if !user_is_allowed('orders', 'view')
376
+ statuses = [
377
+ Order::STATUS_CART,
378
+ Order::STATUS_PENDING,
379
+ Order::STATUS_READY_TO_SHIP,
380
+ Order::STATUS_SHIPPED,
381
+ Order::STATUS_CANCELED
382
+ ]
383
+ options = statuses.collect{ |s| { 'text' => s.capitalize, 'value' => s }}
378
384
  render :json => options
379
385
  end
380
386
 
@@ -397,16 +403,16 @@ module Caboose
397
403
  if Caboose::Setting.exists?(:name => 'google_feed_date_last_submitted')
398
404
  d1 = Caboose::Setting.where(:name => 'google_feed_date_last_submitted').first.value
399
405
  d1 = DateTime.parse(d1)
400
- elsif Order.exists?("status = 'shipped' and date_authorized is not null")
401
- d1 = Order.where("status = ? and date_authorized is not null", 'shipped').reorder("date_authorized DESC").limit(1).pluck('date_authorized')
406
+ elsif Order.exists?("status = ? and date_authorized is not null", Order::STATUS_SHIPPED)
407
+ d1 = Order.where("status = ? and date_authorized is not null", Order::STATUS_SHIPPED).reorder("date_authorized DESC").limit(1).pluck('date_authorized')
402
408
  d1 = DateTime.parse(d1)
403
409
  end
404
410
 
405
411
  # Google Feed Docs
406
412
  # https://support.google.com/trustedstoresmerchant/answer/3272612?hl=en&ref_topic=3272286?hl=en
407
413
  tsv = ["merchant order id\ttracking number\tcarrier code\tother carrier name\tship date"]
408
- if Order.exists?("status = 'shipped' and date_authorized > '#{d1.strftime("%F %T")}'")
409
- Order.where("status = ? and date_authorized > ?", 'shipped', d1).reorder(:id).all.each do |order|
414
+ if Order.exists?("status = ? and date_authorized > '#{d1.strftime("%F %T")}'", Order::STATUS_SHIPPED)
415
+ Order.where("status = ? and date_authorized > ?", Order::STATUS_SHIPPED, d1).reorder(:id).all.each do |order|
410
416
  tracking_numbers = order.line_items.collect{ |li| li.tracking_number }.compact.uniq
411
417
  tn = tracking_numbers && tracking_numbers.count >= 1 ? tracking_numbers[0] : ""
412
418
  tsv << "#{order.id}\t#{tn}\tUPS\t\t#{order.date_shipped.strftime("%F")}"
@@ -47,6 +47,7 @@ module Caboose
47
47
  # Otherwise looking at a category or search parameters
48
48
  @pager = Caboose::Pager.new(params, {
49
49
  'site_id' => @site.id,
50
+ 'on_sale' => '',
50
51
  'category_id' => '',
51
52
  'vendor_id' => '',
52
53
  'vendor_name' => '',
@@ -87,7 +87,21 @@ module Caboose
87
87
 
88
88
  resp.success = save && site.save
89
89
  render :json => resp
90
- end
90
+ end
91
+
92
+ # POST /admin/sites/:id/logo
93
+ def admin_update_logo
94
+ return if !user_is_allowed('sites', 'edit')
95
+
96
+ site = Site.find(params[:id])
97
+ site.logo = params[:logo]
98
+ site.save
99
+
100
+ resp = StdClass.new
101
+ resp.success = true
102
+ resp.attributes = { :image => { :value => site.logo.url(:thumb) }}
103
+ render :json => resp
104
+ end
91
105
 
92
106
  # DELETE /admin/sites/:id
93
107
  def admin_delete
@@ -12,42 +12,7 @@ module Caboose
12
12
  # Non-admin actions
13
13
  #===========================================================================
14
14
 
15
- # GET /my-account
16
- def my_account
17
- return if !logged_in?
18
- @user = logged_in_user
19
- render :layout => 'caboose/modal'
20
- end
21
-
22
- # PUT /my-account
23
- def update_my_account
24
- return if !logged_in?
25
-
26
- resp = StdClass.new
27
- user = logged_in_user
28
15
 
29
- save = true
30
- params.each do |name,value|
31
- case name
32
- when "first_name", "last_name", "username", "email", "phone"
33
- user[name.to_sym] = value
34
- when "password"
35
- confirm = params[:confirm]
36
- if (value != confirm)
37
- resp.error = "Passwords do not match.";
38
- save = false
39
- elsif (value.length < 8)
40
- resp.error = "Passwords must be at least 8 characters.";
41
- save = false
42
- else
43
- user.password = Digest::SHA1.hexdigest(Caboose::salt + value)
44
- end
45
- end
46
- end
47
-
48
- resp.success = save && user.save
49
- render json: resp
50
- end
51
16
 
52
17
  #===========================================================================
53
18
  # Admin actions
@@ -119,7 +119,7 @@ module Caboose
119
119
  when 'alternate_id' then v.alternate_id = value
120
120
  when 'sku' then v.sku = value
121
121
  when 'barcode' then v.barcode = value
122
- when 'price' then v.price = value
122
+ when 'price' then v.price = value
123
123
  when 'quantity_in_stock' then v.quantity_in_stock = value
124
124
  when 'ignore_quantity' then v.ignore_quantity = value
125
125
  when 'allow_backorder' then v.allow_backorder = value
@@ -135,6 +135,16 @@ module Caboose
135
135
  when 'taxable' then v.taxable = value
136
136
  when 'downloadable' then v.downloadable = value
137
137
  when 'download_path' then v.download_path = value
138
+
139
+ when 'sale_price'
140
+ v.sale_price = value
141
+ v.product.delay(:run_at => 3.seconds.from_now).update_on_sale
142
+ when 'date_sale_starts'
143
+ v.date_sale_starts = ModelBinder.local_datetime_to_utc(value, @logged_in_user.timezone)
144
+ v.product.delay(:run_at => v.date_sale_starts).update_on_sale
145
+ when 'date_sale_ends'
146
+ v.date_sale_ends = ModelBinder.local_datetime_to_utc(value, @logged_in_user.timezone)
147
+ v.product.delay(:run_at => v.date_sale_ends).update_on_sale
138
148
  end
139
149
  end
140
150
  resp.success = save && v.save
@@ -380,7 +390,7 @@ module Caboose
380
390
  return unless user_is_allowed_to 'edit', 'sites'
381
391
 
382
392
  resp = Caboose::StdClass.new
383
- variants = params[:model_ids].collect{ |variant_id| Variant.find(variant_id) }
393
+ variants = params[:model_ids].collect{ |variant_id| Variant.find(variant_id) }
384
394
 
385
395
  save = true
386
396
  params.each do |k,value|
@@ -404,6 +414,45 @@ module Caboose
404
414
  when 'taxable' then variants.each { |v| v.taxable = value }
405
415
  when 'downloadable' then variants.each { |v| v.downloadable = value }
406
416
  when 'download_path' then variants.each { |v| v.download_path = value }
417
+
418
+ when 'sale_price'
419
+ variants.each_with_index do |v, i|
420
+ v.sale_price = value
421
+ v.product.delay(:run_at => 3.seconds.from_now).update_on_sale if i == 0
422
+ end
423
+ when 'date_sale_starts'
424
+ variants.each_with_index do |v, i|
425
+ v.date_sale_starts = ModelBinder.update_date(v.date_sale_starts, value, @logged_in_user.timezone)
426
+ if i == 0
427
+ v.product.delay(:run_at => v.date_sale_starts).update_on_sale
428
+ v.product.delay(:run_at => 3.seconds.from_now).update_on_sale
429
+ end
430
+ end
431
+ when 'time_sale_starts'
432
+ variants.each_with_index do |v, i|
433
+ v.date_sale_starts = ModelBinder.update_time(v.date_sale_starts, value, @logged_in_user.timezone)
434
+ if i == 0
435
+ v.product.delay(:run_at => v.date_sale_starts).update_on_sale
436
+ v.product.delay(:run_at => 3.seconds.from_now).update_on_sale
437
+ end
438
+ end
439
+ when 'date_sale_ends'
440
+ variants.each_with_index do |v, i|
441
+ v.date_sale_ends = ModelBinder.update_date(v.date_sale_ends, value, @logged_in_user.timezone)
442
+ if i == 0
443
+ v.product.delay(:run_at => v.date_sale_ends).update_on_sale
444
+ v.product.delay(:run_at => 3.seconds.from_now).update_on_sale
445
+ end
446
+ end
447
+ when 'time_sale_ends'
448
+ variants.each_with_index do |v, i|
449
+ v.date_sale_ends = ModelBinder.update_time(v.date_sale_ends, value, @logged_in_user.timezone)
450
+ if i == 0
451
+ v.product.delay(:run_at => v.date_sale_ends).update_on_sale
452
+ v.product.delay(:run_at => 3.seconds.from_now).update_on_sale
453
+ end
454
+ end
455
+
407
456
  end
408
457
  end
409
458
  variants.each{ |v| v.save }
@@ -46,7 +46,7 @@ module Caboose
46
46
  render :json => { :success => vendor.save }
47
47
  end
48
48
 
49
- # POST /admin/vendors/:id/update/image
49
+ # POST /admin/vendors/:id/image
50
50
  def admin_update_image
51
51
  return if !user_is_allowed('vendors', 'edit')
52
52
 
@@ -55,8 +55,9 @@ module Caboose
55
55
  vendor.save
56
56
 
57
57
  resp = StdClass.new
58
+ resp.success = true
58
59
  resp.attributes = { :image => { :value => vendor.image.url(:thumb) }}
59
- resp.success = vendor.save
60
+ render :json => resp
60
61
  end
61
62
 
62
63
  # GET /admin/vendors/new