caboose-cms 0.5.15 → 0.5.16

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 (40) hide show
  1. checksums.yaml +9 -9
  2. data/app/assets/javascripts/caboose/cart2.js +98 -0
  3. data/app/assets/javascripts/caboose/model/index_table.js +82 -30
  4. data/app/assets/javascripts/caboose/model/model_binder.js +4 -4
  5. data/app/assets/stylesheets/caboose/admin.css +1 -0
  6. data/app/assets/stylesheets/caboose/admin_main.css +0 -42
  7. data/app/assets/stylesheets/caboose/cart.scss +41 -0
  8. data/app/assets/stylesheets/caboose/checkout.css.scss +2 -3
  9. data/app/assets/stylesheets/caboose/message_boxes.scss +49 -0
  10. data/app/assets/templates/caboose/cart/add_to_cart.jst.ejs +1 -1
  11. data/app/controllers/caboose/block_types_controller.rb +3 -1
  12. data/app/controllers/caboose/cart_controller.rb +30 -23
  13. data/app/controllers/caboose/checkout_controller.rb +11 -1
  14. data/app/controllers/caboose/products_controller.rb +28 -14
  15. data/app/controllers/caboose/stackable_groups_controller.rb +107 -0
  16. data/app/models/caboose/line_item.rb +20 -6
  17. data/app/models/caboose/order.rb +2 -1
  18. data/app/models/caboose/order_package.rb +103 -0
  19. data/app/models/caboose/product.rb +2 -1
  20. data/app/models/caboose/schema.rb +45 -3
  21. data/app/models/caboose/shipping_calculator.rb +101 -60
  22. data/app/models/caboose/shipping_package.rb +80 -0
  23. data/app/models/caboose/site.rb +3 -1
  24. data/app/models/caboose/stackable_group.rb +17 -0
  25. data/app/models/caboose/tax_calculator.rb +1 -2
  26. data/app/models/caboose/variant.rb +2 -5
  27. data/app/views/caboose/cart/index.html.erb +19 -6
  28. data/app/views/caboose/checkout/_cart.html.erb +49 -52
  29. data/app/views/caboose/checkout/empty.html.erb +9 -2
  30. data/app/views/caboose/checkout/step_one.html.erb +2 -3
  31. data/app/views/caboose/checkout/step_three.html.erb +28 -10
  32. data/app/views/caboose/checkout/step_two.html.erb +2 -4
  33. data/app/views/caboose/pages/admin_edit_content.html.erb +1 -1
  34. data/app/views/caboose/products/admin_index.html.erb +12 -11
  35. data/app/views/caboose/sites/admin_edit.html.erb +33 -6
  36. data/app/views/caboose/stackable_groups/admin_index.html.erb +43 -0
  37. data/config/routes.rb +15 -6
  38. data/lib/caboose/version.rb +1 -1
  39. data/lib/tasks/caboose.rake +7 -1
  40. metadata +36 -14
@@ -3,6 +3,7 @@ module Caboose
3
3
  self.table_name = 'store_products'
4
4
  self.primary_key = 'id'
5
5
 
6
+ belongs_to :stackable_group, :class_name => 'Caboose::StackableGroup'
6
7
  belongs_to :vendor, :class_name => 'Caboose::Vendor'
7
8
  has_many :customizations, :class_name => 'Caboose::Product', :through => :customization_memberships
8
9
  has_many :customization_memberships, :class_name => 'Caboose::CustomizationMembership'
@@ -66,7 +67,7 @@ module Caboose
66
67
  :vendor => self.vendor,
67
68
  :categories => self.categories,
68
69
  :variants => self.variants,
69
- :images => self.product_images
70
+ :images => self.product_images
70
71
  })
71
72
  end
72
73
 
@@ -242,12 +242,12 @@ class Caboose::Schema < Caboose::Utilities::Schema
242
242
  ],
243
243
  Caboose::LineItem => [
244
244
  [ :order_id , :integer ],
245
+ [ :order_package_id , :integer ],
245
246
  [ :variant_id , :integer ],
246
247
  [ :parent_id , :integer ],
247
248
  [ :quantity , :integer , :default => 0 ],
248
249
  [ :status , :string ],
249
- [ :tracking_number , :string ],
250
- #[ :unit_price , :numeric ],
250
+ [ :tracking_number , :string ],
251
251
  [ :price , :numeric , :default => 0 ],
252
252
  [ :notes , :text ],
253
253
  [ :custom1 , :string ],
@@ -311,6 +311,12 @@ class Caboose::Schema < Caboose::Utilities::Schema
311
311
  [ :order_id , :integer ],
312
312
  [ :discount_id , :integer ]
313
313
  ],
314
+ Caboose::OrderPackage => [
315
+ [ :order_id , :integer ],
316
+ [ :shipping_package_id , :integer ],
317
+ [ :status , :string ],
318
+ [ :tracking_number , :string ]
319
+ ],
314
320
  Caboose::Page => [
315
321
  [ :site_id , :integer ],
316
322
  [ :parent_id , :integer ],
@@ -396,7 +402,8 @@ class Caboose::Schema < Caboose::Utilities::Schema
396
402
  [ :date_available , :datetime ],
397
403
  [ :custom_input , :text ],
398
404
  [ :sort_order , :integer ],
399
- [ :featured , :boolean , :default => false ]
405
+ [ :featured , :boolean , :default => false ],
406
+ [ :stackable_group_id , :integer ]
400
407
  ],
401
408
  Caboose::ProductImage => [
402
409
  [ :product_id , :integer ],
@@ -449,6 +456,16 @@ class Caboose::Schema < Caboose::Utilities::Schema
449
456
  [ :name , :string ],
450
457
  [ :value , :text ]
451
458
  ],
459
+ Caboose::ShippingPackage => [
460
+ [ :carrier , :string ],
461
+ [ :service_code , :string ],
462
+ [ :service_name , :string ],
463
+ [ :length , :decimal ],
464
+ [ :width , :decimal ],
465
+ [ :height , :decimal ],
466
+ [ :volume , :decimal ],
467
+ [ :price , :decimal ]
468
+ ],
452
469
  Caboose::Site => [
453
470
  [ :name , :string ],
454
471
  [ :description , :text ],
@@ -469,6 +486,15 @@ class Caboose::Schema < Caboose::Utilities::Schema
469
486
  [ :authentication , :string ], # :plain, :login, :cram_md5.
470
487
  [ :enable_starttls_auto , :boolean , { :default => true }]
471
488
  ],
489
+ Caboose::StackableGroup => [
490
+ [ :name , :string ],
491
+ [ :extra_length , :decimal ],
492
+ [ :extra_width , :decimal ],
493
+ [ :extra_height , :decimal ],
494
+ [ :max_length , :decimal ],
495
+ [ :max_width , :decimal ],
496
+ [ :max_height , :decimal ]
497
+ ],
472
498
  Caboose::User => [
473
499
  [ :first_name , :string ],
474
500
  [ :last_name , :string ],
@@ -502,6 +528,7 @@ class Caboose::Schema < Caboose::Utilities::Schema
502
528
  [ :length , :decimal ],
503
529
  [ :width , :decimal ],
504
530
  [ :height , :decimal ],
531
+ [ :volume , :decimal ],
505
532
  [ :cylinder , :boolean ],
506
533
  [ :option1 , :string ],
507
534
  [ :option2 , :string ],
@@ -687,6 +714,21 @@ class Caboose::Schema < Caboose::Utilities::Schema
687
714
  :slug => 'products'
688
715
  })
689
716
  end
717
+
718
+ if !Caboose::ShippingPackage.where(:carrier => 'USPS', :service_code => "29").exists?
719
+ Caboose::ShippingPackage.create(:carrier => 'USPS', :service_code => "29", :service_name => "USPS Priority Mail 1-Day Padded Flat Rate Envelope", :price=>610 , :volume => 180)
720
+ end
721
+ if !Caboose::ShippingPackage.where(:carrier => 'USPS', :service_code => "28").exists?
722
+ Caboose::ShippingPackage.create(:carrier => 'USPS', :service_code => "28", :service_name => "USPS Priority Mail 1-Day Small Flat Rate Box" , :price=>595 , :length => 8.625 , :width => 5.375 , :height => 1.625 , :volume => 75.334)
723
+ end
724
+ if !Caboose::ShippingPackage.where(:carrier => 'USPS', :service_code => "17").exists?
725
+ Caboose::ShippingPackage.create(:carrier => 'USPS', :service_code => "17", :service_name => "USPS Priority Mail 1-Day Medium Flat Rate Box" , :price=>1265 , :length => 11 , :width => 8.5 , :height => 5.5 , :volume => 514.25)
726
+ Caboose::ShippingPackage.create(:carrier => 'USPS', :service_code => "17", :service_name => "USPS Priority Mail 1-Day Medium Flat Rate Box" , :price=>1265 , :length => 13.625 , :width => 11.875 , :height => 3.375 , :volume => 546.06)
727
+ end
728
+ if !Caboose::ShippingPackage.where(:carrier => 'USPS', :service_code => "22").exists?
729
+ Caboose::ShippingPackage.create(:carrier => 'USPS', :service_code => "22", :service_name => "USPS Priority Mail 1-Day Large Flat Rate Box" , :price=>1790 , :length => 12 , :width => 12 , :height => 5.5 , :volume => 792 )
730
+ Caboose::ShippingPackage.create(:carrier => 'USPS', :service_code => "22", :service_name => "USPS Priority Mail 1-Day Large Flat Rate Box" , :price=>1790 , :length => 23.6875 , :width => 11.75 , :height => 3 , :volume => 834.98)
731
+ end
690
732
 
691
733
  end
692
734
  end
@@ -3,72 +3,48 @@ include ActiveMerchant::Shipping
3
3
 
4
4
  module Caboose
5
5
  class ShippingCalculator
6
+
6
7
  def self.rates(order)
7
- return [] if Caboose::shipping.nil?
8
-
9
- total = 0.0
10
- weight = 0.0
11
-
12
- order.line_items.each do |li|
13
- total = total + (li.variant.shipping_unit_value.nil? ? 0 : li.variant.shipping_unit_value)
14
- weight = weight + (li.variant.weight || 0)
15
- end
16
-
17
- length = 0
18
- width = 0
19
- height = 0
20
-
21
- if total <= 5
22
- length = 15.5
23
- width = 9.5
24
- height = 6
25
- elsif total <= 10
26
- length = 12
27
- width = 8
28
- height = 5
29
- else
30
- length = 20
31
- width = 16
32
- height = 14
33
- end
8
+ return [] if Caboose::store_shipping.nil?
34
9
 
10
+ ss = Caboose::store_shipping
35
11
  origin = Location.new(
36
- :country => Caboose::shipping[:origin][:country],
37
- :state => Caboose::shipping[:origin][:state],
38
- :city => Caboose::shipping[:origin][:city],
39
- :zip => Caboose::shipping[:origin][:zip]
40
- )
41
-
12
+ :country => ss[:origin][:country],
13
+ :state => ss[:origin][:state],
14
+ :city => ss[:origin][:city],
15
+ :zip => ss[:origin][:zip]
16
+ )
42
17
  destination = Location.new(
43
- :country => Caboose::shipping[:origin][:country],
18
+ :country => ss[:origin][:country],
44
19
  :state => order.shipping_address.state,
45
20
  :city => order.shipping_address.city,
46
21
  :postal_code => order.shipping_address.zip
47
- )
48
-
49
- packages = [Package.new(weight, [length, width, height], :units => :imperial)]
50
-
51
- ups = UPS.new(
52
- :key => Caboose::shipping[:ups][:key],
53
- :login => Caboose::shipping[:ups][:username],
54
- :password => Caboose::shipping[:ups][:password],
55
- :origin_account => Caboose::shipping[:ups][:origin_account]
56
- )
57
-
58
- ups_response = ups.find_rates(origin, destination, packages)
59
-
60
- rates = ups_response.rates.collect do |rate|
61
- next if Caboose::allowed_shipping_method_codes && !Caboose::allowed_shipping_method_codes.index(rate.service_code)
62
-
63
- {
64
- :service_code => rate.service_code,
65
- :service_name => rate.service_name,
66
- :total_price => rate.total_price.to_d / 100,
67
- :negotiated_rate => rate.negotiated_rate
68
- }
69
- end
70
-
71
- return rates.compact
22
+ )
23
+ ups = ss[:ups] ? UPS.new(:key => ss[:ups][:key], :login => ss[:ups][:username], :password => ss[:ups][:password], :origin_account => ss[:ups][:origin_account]) : nil
24
+ usps = ss[:usps] ? USPS.new(:login => ss[:usps][:username]) : nil
25
+
26
+ all_rates = []
27
+ order.packages.each do |op|
28
+ sp = op.shipping_package
29
+ package = op.activemerchant_package
30
+ rates = []
31
+ if ups
32
+ resp = ups.find_rates(origin, destination, package)
33
+ resp.rates.sort_by(&:price).each do |rate|
34
+ next if rate.service_code != sp.service_code
35
+ rates << { :carrier => 'UPS', :service_code => rate.service_code, :service_name => rate.service_name, :price => rate.total_price.to_d / 100 }
36
+ end
37
+ end
38
+ if usps
39
+ resp = usps.find_rates(origin, destination, package)
40
+ resp.rates.sort_by(&:price).each do |rate|
41
+ next if rate.service_code != sp.service_code
42
+ rates << { :carrier => 'USPS', :service_code => rate.service_code, :service_name => rate.service_name, :total_price => rate.total_price.to_d / 100 }
43
+ end
44
+ end
45
+ all_rates << [op, rates]
46
+ end
47
+ return all_rates
72
48
  end
73
49
 
74
50
  def self.rate(order)
@@ -76,6 +52,71 @@ module Caboose
76
52
  self.rates(order).each { |rate| return rate if rate[:service_code] == order.shipping_method_code }
77
53
  return nil
78
54
  end
55
+
56
+ # Calculates the packages required for all the items in the order
57
+ #def self.packages_for_order(order)
58
+ #
59
+ # # Make sure all the items in the order have attributes set
60
+ # order.line_items.each do |li|
61
+ # v = li.variant
62
+ # Caboose.log("Error: variant #{v.id} has a zero weight") and return false if v.weight.nil? || v.weight == 0
63
+ # next if v.volume && v.volume > 0
64
+ # Caboose.log("Error: variant #{v.id} has a zero length") and return false if v.length.nil? || v.length == 0
65
+ # Caboose.log("Error: variant #{v.id} has a zero width" ) and return false if v.width.nil? || v.width == 0
66
+ # Caboose.log("Error: variant #{v.id} has a zero height") and return false if v.height.nil? || v.height == 0
67
+ # v.volume = v.length * v.width * v.height
68
+ # v.save
69
+ # end
70
+ #
71
+ # # Reorder the items in the order by volume
72
+ # h = {}
73
+ # order.line_items.each do |li|
74
+ # (1..li.quantity).each do |i|
75
+ # v = li.variant
76
+ # h[v.volume] = v
77
+ # end
78
+ # end
79
+ # variants = h.sort_by{ |k,v| k }.collect{ |x| x[1] }
80
+ #
81
+ # all_packages = ShippingPackage.reorder(:price).all
82
+ # packages = []
83
+ #
84
+ # # Now go through each variant and fit it in a new or existing package
85
+ # variants.each do |v|
86
+ #
87
+ # # See if the item will fit in any of the existing packages
88
+ # it_fits = false
89
+ # packages.each do |h|
90
+ # it_fits = h.shipping_package.fits(h.variants, v)
91
+ # if it_fits
92
+ # h.variants << v
93
+ # break
94
+ # end
95
+ # end
96
+ # next if it_fits
97
+ #
98
+ # # Otherwise find the cheapest package the item will fit into
99
+ # all_packages.each do |p|
100
+ # if p.fits(v)
101
+ # packages << StdClass.new('shipping_package' => p, 'variants' => [v])
102
+ # break
103
+ # end
104
+ # end
105
+ #
106
+ # end
107
+ #
108
+ # return packages
109
+ #
110
+ # #arr = []
111
+ # #packages.each do |h|
112
+ # # p = h.package
113
+ # # weight = 0.0
114
+ # # h.variants.each{ |v| weight = weight + v.weight }
115
+ # # weight = weight * 0.035274
116
+ # # arr << Package.new(weight, [p.length, p.width, p.height], :units => :imperial)
117
+ # #end
118
+ # #return arr
119
+ #
120
+ #end
79
121
  end
80
122
  end
81
-
@@ -0,0 +1,80 @@
1
+ require 'box_packer'
2
+
3
+ module Caboose
4
+ class ShippingPackage < ActiveRecord::Base
5
+ self.table_name = 'store_shipping_packages'
6
+ attr_accessible :id, :carrier, :service_code, :service_name, :length, :width, :height, :volume, :price
7
+
8
+ def fits(variants)
9
+
10
+ arr = variants.is_a?(Array) ? variants : [variants]
11
+ rigid = []
12
+ floppy = []
13
+ arr.each do |v|
14
+ if v.length && v.length > 0 && v.width && v.width > 0 && v.height && v.height > 0
15
+ rigid << v
16
+ else
17
+ floppy << v
18
+ end
19
+ end
20
+ rigid_volume = 0.0
21
+ floppy_volume = 0.0
22
+ rigid.each { |v| rigid_volume = rigid_volume + v.volume }
23
+ floppy.each{ |v| floppy_volume = floppy_volume + v.volume }
24
+ return false if (rigid_volume + floppy_volume) > self.volume
25
+ rigid_boxes = self.boxes(rigid)
26
+
27
+ it_fits = false
28
+ BoxPacker.container [self.length, self.width, self.height] do
29
+ rigid_boxes.each{ |arr| add_item arr }
30
+ count = pack!
31
+ it_fits = true if count == rigid_boxes.count
32
+ end
33
+ return it_fits
34
+
35
+ end
36
+
37
+ # Gets the 3d dimensions of the variants after they're stacked
38
+ def boxes(rigid_variants)
39
+ stackable = {}
40
+ nonstackable = []
41
+ rigid_variants.each do |v|
42
+ sgid = v.product.stackable_group_id
43
+ if sgid
44
+ stackable[sgid] = [] if stackable[sgid].nil?
45
+ stackable[sgid] << v
46
+ else
47
+ nonstackable << [v.length, v.width, v.height]
48
+ end
49
+ end
50
+
51
+ stackable.each do |sgid, arr|
52
+ sg = arr[0].product.stackable_group
53
+ l = 0.0
54
+ w = 0.0
55
+ h = 0.0
56
+ arr.each do |v|
57
+ if l+sg.extra_length >= sg.max_length || w+sg.extra_width >= sg.max_width || h+sg.extra_height >= sg.max_height
58
+ nonstackable << [l, w, h]
59
+ l = 0.0
60
+ w = 0.0
61
+ h = 0.0
62
+ end
63
+ if l == 0.0
64
+ l = v.length
65
+ w = v.width
66
+ h = v.height
67
+ else
68
+ l = l + sg.extra_length
69
+ w = w + sg.extra_width
70
+ h = h + sg.extra_height
71
+ end
72
+ end
73
+ nonstackable << [l, w, h] if l > 0
74
+ end
75
+
76
+ return nonstackable
77
+ end
78
+
79
+ end
80
+ end
@@ -1,7 +1,9 @@
1
1
 
2
2
  class Caboose::Site < ActiveRecord::Base
3
3
  self.table_name = "sites"
4
-
4
+
5
+ has_many :block_type_site_memberships, :class_name => 'Caboose::BlockTypeSiteMembership', :dependent => :delete_all
6
+ has_many :block_types, :through => :block_type_site_memberships
5
7
  has_many :site_memberships, :class_name => 'Caboose::SiteMembership', :dependent => :delete_all
6
8
  has_many :domains, :class_name => 'Caboose::Domain', :dependent => :delete_all
7
9
  has_many :post_categories, :class_name => 'Caboose::PostCategory'
@@ -0,0 +1,17 @@
1
+ module Caboose
2
+ class StackableGroup < ActiveRecord::Base
3
+ self.table_name = 'store_stackable_groups'
4
+
5
+ has_many :products
6
+ attr_accessible :id,
7
+ :name,
8
+ :extra_length,
9
+ :extra_width,
10
+ :extra_height,
11
+ :max_length,
12
+ :max_width,
13
+ :max_height
14
+
15
+ end
16
+ end
17
+
@@ -1,7 +1,6 @@
1
1
  module Caboose
2
2
  class TaxCalculator
3
- def self.tax_rate(address)
4
- ap '--HOOK calculate tax'
3
+ def self.tax_rate(address)
5
4
  return 0 if address.state.downcase != 'al'
6
5
  city = address.city.downcase
7
6
  rate = 0.00
@@ -76,11 +76,8 @@ module Caboose
76
76
 
77
77
  def as_json(options={})
78
78
  self.attributes.merge({
79
- :images => if self.product_images.any?
80
- self.product_images
81
- else
82
- [self.product.product_images.first]
83
- end
79
+ :images => self.product_images.any? ? self.product_images : [self.product.product_images.first],
80
+ :title => "#{self.product.title} (#{self.options.join(', ')})"
84
81
  })
85
82
  end
86
83
 
@@ -1,8 +1,21 @@
1
- <div class="wrapper">
2
- <div id="cart"></div>
3
- </div>
1
+ <div class="constrain">
2
+ <div id='cart'></div>
3
+ </div>
4
+
5
+ <% content_for :caboose_css do %>
6
+ <%= stylesheet_link_tag 'caboose/message_boxes' %>
7
+ <%= stylesheet_link_tag 'caboose/model_binder' %>
8
+ <%= stylesheet_link_tag 'caboose/cart' %>
9
+ <% end %>
4
10
 
5
11
  <% content_for :caboose_js do %>
6
- <%= javascript_include_tag 'caboose/cart' %>
7
- <%= javascript_include_tag 'caboose/product' %>
8
- <% end %>
12
+ <%= javascript_include_tag 'caboose/model/all' %>
13
+ <%= javascript_include_tag 'caboose/cart2' %>
14
+ <script type='text/javascript'>
15
+
16
+ $(document).ready(function() {
17
+ var controller = new Cart();
18
+ });
19
+
20
+ </script>
21
+ <% end %>