caboose-cms 0.8.24 → 0.8.25

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,84 @@
1
+ module Caboose
2
+ class VariantChildrenController < Caboose::ApplicationController
3
+
4
+ #=============================================================================
5
+ # Admin actions
6
+ #=============================================================================
7
+
8
+ # @route GET /admin/products/:product_id/variants/:variant_id/children/json
9
+ def admin_json
10
+ return if !user_is_allowed('products', 'view')
11
+
12
+ pager = Caboose::PageBarGenerator.new(params, {
13
+ 'parent_id' => params[:variant_id]
14
+ }, {
15
+ 'model' => 'Caboose::VariantChild',
16
+ 'sort' => 'parent_id',
17
+ 'desc' => false,
18
+ 'base_url' => "/admin/products/#{params[:product_id]}/variants/#{params[:variant_id]}/children",
19
+ 'items_per_page' => 100,
20
+ 'use_url_params' => false
21
+ })
22
+ render :json => {
23
+ :pager => pager,
24
+ :models => pager.items.as_json(:include => { :variant => { :methods => :full_title }})
25
+ }
26
+ end
27
+
28
+ # @route GET /admin/products/:product_id/variants/:variant_id/children/:id/json
29
+ def admin_json_single
30
+ return if !user_is_allowed('products', 'view')
31
+
32
+ vc = VariantChild.find(params[:id])
33
+ render :json => vc.as_json(:include => { :variant => { :methods => :full_title }})
34
+ end
35
+
36
+ # @route POST /admin/products/:product_id/variants/:parent_id/children
37
+ def admin_add
38
+ resp = Caboose::StdClass.new
39
+
40
+ if params[:parent_id] == params[:variant_id]
41
+ resp.error = "Can't add the same variant as a child."
42
+ else
43
+ vc = VariantChild.create(
44
+ :parent_id => params[:parent_id],
45
+ :variant_id => params[:variant_id],
46
+ :quantity => params[:quantity] ? params[:quantity] : 1
47
+ )
48
+ resp.new_id = vc.id
49
+ resp.success = true
50
+ end
51
+ render :json => resp
52
+ end
53
+
54
+ # @route PUT /admin/products/:product_id/variants/:parent_variant_id/children/:id
55
+ def admin_update
56
+ return if !user_is_allowed('variants', 'edit')
57
+
58
+ resp = Caboose::StdClass.new
59
+ vcs = params[:id] == 'bulk' ? params[:model_ids].collect{ |model_id| VariantChild.find(model_id) } : [VariantChild.find(params[:id])]
60
+
61
+ params.each do |name,value|
62
+ case name
63
+ when 'parent_id' then vcs.each{ |vc| vc.parent_id = value }
64
+ when 'variant_id' then vcs.each{ |vc| vc.variant_id = value }
65
+ when 'quantity' then vcs.each{ |vc| vc.quantity = value }
66
+ end
67
+ end
68
+ vcs.each{ |vc| vc.save }
69
+ resp.success = true
70
+ render :json => resp
71
+ end
72
+
73
+ # @route DELETE /admin/products/:product_id/variants/:variant_id/children/:id
74
+ def admin_delete
75
+ return if !user_is_allowed('variants', 'delete')
76
+ vc_ids = params[:id] == 'bulk' ? params[:model_ids] : [params[:id]]
77
+ vc_ids.each do |vc_id|
78
+ VariantChild.where(:id => vc_id).destroy_all
79
+ end
80
+ render :json => { :success => true }
81
+ end
82
+
83
+ end
84
+ end
@@ -75,7 +75,7 @@ module Caboose
75
75
  v = Variant.find(params[:id])
76
76
  render :json => v
77
77
  end
78
-
78
+
79
79
  # @route GET /admin/products/:product_id/variants/:id/download-url
80
80
  def admin_download_url
81
81
  return if !user_is_allowed('variants', 'edit')
@@ -148,7 +148,7 @@ module Caboose
148
148
  @product = @variant.product
149
149
  render :layout => 'caboose/admin'
150
150
  end
151
-
151
+
152
152
  # @route PUT /admin/products/:product_id/variants/:id/attach-to-image
153
153
  def admin_attach_to_image
154
154
  render :json => false if !user_is_allowed('variants', 'edit')
@@ -353,6 +353,7 @@ module Caboose
353
353
  when 'option3' then v.option3 = value
354
354
  when 'requires_shipping' then v.requires_shipping = value
355
355
  when 'taxable' then v.taxable = value
356
+ when 'is_bundle' then v.is_bundle = value
356
357
  when 'flat_rate_shipping' then v.flat_rate_shipping = value
357
358
  when 'flat_rate_shipping_single' then v.flat_rate_shipping_single = value
358
359
  when 'flat_rate_shipping_combined' then v.flat_rate_shipping_combined = value
@@ -376,6 +377,7 @@ module Caboose
376
377
  v.date_sale_ends = ModelBinder.local_datetime_to_utc(value, @logged_in_user.timezone)
377
378
  v.product.delay(:run_at => v.date_sale_ends , :queue => 'caboose_store').update_on_sale
378
379
  v.product.delay(:run_at => 3.seconds.from_now, :queue => 'caboose_store').update_on_sale
380
+
379
381
  end
380
382
  end
381
383
  resp.success = save && v.save
@@ -427,6 +429,9 @@ module Caboose
427
429
  resp = Caboose::StdClass.new
428
430
  p = Caboose::Product.find(params[:product_id])
429
431
 
432
+ pd = @site.product_default
433
+ vd = @site.variant_default
434
+
430
435
  v = Caboose::Variant.where(:alternate_id => params[:alternate_id]).first
431
436
  v = Caboose::Variant.new(:product_id => p.id) if v.nil?
432
437
 
@@ -434,10 +439,26 @@ module Caboose
434
439
  v.alternate_id = params[:alternate_id].strip
435
440
  v.quantity_in_stock = params[:quantity_in_stock].strip.to_i
436
441
  v.price = '%.2f' % params[:price].strip.to_f
437
- v.option1 = params[:option1] if p.option1
438
- v.option2 = params[:option2] if p.option2
439
- v.option3 = params[:option3] if p.option3
440
- v.status = 'Active'
442
+ v.option1 = params[:option1] if p.option1
443
+ v.option2 = params[:option2] if p.option2
444
+ v.option3 = params[:option3] if p.option3
445
+
446
+ v.cost = vd.cost
447
+ v.available = vd.available
448
+ v.ignore_quantity = vd.ignore_quantity
449
+ v.allow_backorder = vd.allow_backorder
450
+ v.weight = vd.weight
451
+ v.length = vd.length
452
+ v.width = vd.width
453
+ v.height = vd.height
454
+ v.volume = vd.volume
455
+ v.cylinder = vd.cylinder
456
+ v.requires_shipping = vd.requires_shipping
457
+ v.taxable = vd.taxable
458
+ v.status = vd.status
459
+ v.downloadable = vd.downloadable
460
+ v.is_bundle = vd.is_bundle
461
+
441
462
  v.save
442
463
 
443
464
  resp.success = true
@@ -0,0 +1,25 @@
1
+ #
2
+ # ProductDefault
3
+ #
4
+ # :: Class Methods
5
+ # :: Instance Methods
6
+
7
+ module Caboose
8
+ class ProductDefault < ActiveRecord::Base
9
+ self.table_name = 'store_product_defaults'
10
+
11
+ belongs_to :site
12
+ belongs_to :vendor
13
+ attr_accessible :id ,
14
+ :site_id ,
15
+ :vendor_id ,
16
+ :option1 ,
17
+ :option2 ,
18
+ :option3 ,
19
+ :status ,
20
+ :on_sale ,
21
+ :allow_gift_wrap ,
22
+ :gift_wrap_price
23
+
24
+ end
25
+ end
@@ -604,7 +604,18 @@ class Caboose::Schema < Caboose::Utilities::Schema
604
604
  [ :allow_gift_wrap , :boolean , { :default => false }],
605
605
  [ :gift_wrap_price , :decimal , { :precision => 8, :scale => 2 }],
606
606
  [ :media_category_id , :integer ]
607
- ],
607
+ ],
608
+ Caboose::ProductDefault => [
609
+ [ :site_id , :integer ],
610
+ [ :vendor_id , :integer ],
611
+ [ :option1 , :string ],
612
+ [ :option2 , :string ],
613
+ [ :option3 , :string ],
614
+ [ :status , :string ],
615
+ [ :on_sale , :boolean , { :default => false }],
616
+ [ :allow_gift_wrap , :boolean , { :default => false }],
617
+ [ :gift_wrap_price , :decimal , { :precision => 8, :scale => 2 }]
618
+ ],
608
619
  Caboose::ProductImage => [
609
620
  [ :product_id , :integer ],
610
621
  [ :alternate_id , :string ],
@@ -802,7 +813,10 @@ class Caboose::Schema < Caboose::Utilities::Schema
802
813
  [ :weight_unit , :string , { :default => 'oz' }],
803
814
  [ :download_url_expires_in , :string , { :default => 5 }],
804
815
  [ :starting_invoice_number , :integer , { :default => 1000 }],
805
- [ :default_payment_terms , :string , { :default => 'pia' }]
816
+ [ :default_payment_terms , :string , { :default => 'pia' }],
817
+ [ :default_vendor_id , :integer ],
818
+ [ :default_product_status , :string ],
819
+ [ :default_taxable , :boolean ]
806
820
  ],
807
821
  Caboose::Subscription => [
808
822
  [ :site_id , :integer ],
@@ -900,7 +914,39 @@ class Caboose::Schema < Caboose::Utilities::Schema
900
914
  [ :option3_sort_order , :integer , { :default => 0 }],
901
915
  [ :sort_order , :integer , { :default => 0 }],
902
916
  [ :downloadable , :boolean , { :default => false }],
903
- [ :download_path , :string ]
917
+ [ :download_path , :string ],
918
+ [ :is_bundle , :boolean , { :default => false }]
919
+ ],
920
+ Caboose::VariantChild => [
921
+ [ :parent_id , :integer ],
922
+ [ :variant_id , :integer ],
923
+ [ :quantity , :integer ]
924
+ ],
925
+ Caboose::VariantDefault => [
926
+ [ :site_id , :integer ],
927
+ [ :cost , :decimal , { :precision => 8, :scale => 2, :default => 0.00 }],
928
+ [ :price , :decimal , { :precision => 8, :scale => 2, :default => 0.00 }],
929
+ [ :available , :boolean , { :default => true }],
930
+ [ :quantity_in_stock , :integer , { :default => 0 }],
931
+ [ :ignore_quantity , :boolean , { :default => false }],
932
+ [ :allow_backorder , :boolean , { :default => false }],
933
+ [ :weight , :decimal ],
934
+ [ :length , :decimal ],
935
+ [ :width , :decimal ],
936
+ [ :height , :decimal ],
937
+ [ :volume , :decimal ],
938
+ [ :cylinder , :boolean , { :default => false }],
939
+ [ :requires_shipping , :boolean , { :default => true }],
940
+ [ :taxable , :boolean , { :default => true }],
941
+ [ :shipping_unit_value , :numeric ],
942
+ [ :flat_rate_shipping , :boolean , { :default => false }],
943
+ [ :flat_rate_shipping_package_id , :integer ],
944
+ [ :flat_rate_shipping_method_id , :integer ],
945
+ [ :flat_rate_shipping_single , :decimal , { :precision => 8, :scale => 2, :default => 0.0 }],
946
+ [ :flat_rate_shipping_combined , :decimal , { :precision => 8, :scale => 2, :default => 0.0 }],
947
+ [ :status , :string ],
948
+ [ :downloadable , :boolean , { :default => false }],
949
+ [ :is_bundle , :boolean , { :default => false }]
904
950
  ],
905
951
  Caboose::Vendor => [
906
952
  [ :site_id , :integer ],
@@ -44,6 +44,18 @@ class Caboose::Site < ActiveRecord::Base
44
44
  return c
45
45
  end
46
46
 
47
+ def product_default
48
+ pd = Caboose::ProductDefault.where(:site_id => self.id).first
49
+ pd = Caboose::ProductDefault.create(:site_id => self.id) if pd.nil?
50
+ return pd
51
+ end
52
+
53
+ def variant_default
54
+ vd = Caboose::VariantDefault.where(:site_id => self.id).first
55
+ vd = Caboose::VariantDefault.create(:site_id => self.id) if vd.nil?
56
+ return vd
57
+ end
58
+
47
59
  def self.id_for_domain(domain)
48
60
  d = Caboose::Domain.where(:domain => domain).first
49
61
  return nil if d.nil?
@@ -75,9 +75,10 @@ class Caboose::Utilities::Schema
75
75
  end
76
76
 
77
77
  # Column exists, but not with the correct data type, try to change it
78
- else
79
- c.execute("alter table #{tbl} alter column #{col[0]} type #{col[1]} using cast(#{col[0]} as #{col[1]})")
80
-
78
+ else
79
+ dct = col[1] == 'string' || col[1] == :string ? 'text' : col[1]
80
+ c.execute("alter table #{tbl} alter column #{col[0]} type #{dct} using cast(#{col[0]} as #{dct})")
81
+
81
82
  end
82
83
  if col[0].to_s == model.primary_key
83
84
  c.execute("alter table #{tbl} add primary key (\"#{col[0].to_s}\")")
@@ -16,10 +16,12 @@ module Caboose
16
16
  belongs_to :option1_media, :class_name => 'Caboose::Media'
17
17
  belongs_to :option2_media, :class_name => 'Caboose::Media'
18
18
  belongs_to :option3_media, :class_name => 'Caboose::Media'
19
+ has_many :variant_childen, :class_name => 'Caboose::Variant'
19
20
 
20
21
  attr_accessible :id,
21
22
  :alternate_id,
22
23
  :product_id,
24
+ :sku,
23
25
  :barcode, # Returns the barcode value of the variant.
24
26
  :cost, # Cost of goods (don't show to customer)
25
27
  :price, # Variant’s price.
@@ -37,6 +39,7 @@ module Caboose
37
39
  :length, # Length of variant in inches
38
40
  :width, # Width of variant in inches
39
41
  :height, # Height of variant in inches
42
+ :volume,
40
43
  :option1, # Returns the value of option1 for given variant
41
44
  :option2, # If a product has a second option defined, then returns the value of this variant's option2.
42
45
  :option3, # If a product has a third option defined, then returns the value of this variant's option3.
@@ -45,10 +48,12 @@ module Caboose
45
48
  :option3_color,
46
49
  :option1_media_id,
47
50
  :option2_media_id,
48
- :option3_media_id,
51
+ :option3_media_id,
52
+ :option1_sort_order,
53
+ :option2_sort_order,
54
+ :option3_sort_order,
49
55
  :requires_shipping, # Returns true if the variant is shippable or false if it is a service or a digital good.
50
- :taxable, # Returns true if the variant is taxable or false if it is not.
51
- :sku,
56
+ :taxable, # Returns true if the variant is taxable or false if it is not.
52
57
  :available,
53
58
  :cylinder,
54
59
  :shipping_unit_value,
@@ -56,7 +61,11 @@ module Caboose
56
61
  :flat_rate_shipping_single,
57
62
  :flat_rate_shipping_combined,
58
63
  :flat_rate_shipping_method_id,
59
- :flat_rate_shipping_package_id
64
+ :flat_rate_shipping_package_id,
65
+ :sort_order,
66
+ :downloadable,
67
+ :download_path,
68
+ :is_bundle
60
69
 
61
70
  after_initialize do |v|
62
71
  v.price = 0.00 if v.price.nil?
@@ -114,6 +123,11 @@ module Caboose
114
123
  return self.options.join(' / ')
115
124
  end
116
125
 
126
+ def full_title
127
+ return self.product.title if self.options.count == 0
128
+ return "#{self.product.title} - #{self.title}"
129
+ end
130
+
117
131
  def options
118
132
  arr = []
119
133
  arr << self.option1 if self.option1 && self.option1.strip.length > 0
@@ -0,0 +1,13 @@
1
+ module Caboose
2
+ class VariantChild < ActiveRecord::Base
3
+ self.table_name = 'store_variant_children'
4
+
5
+ belongs_to :parent, :class_name => 'Caboose::Variant'
6
+ belongs_to :variant, :class_name => 'Caboose::Variant'
7
+ attr_accessible :id,
8
+ :parent_id,
9
+ :variant_id,
10
+ :quantity
11
+
12
+ end
13
+ end
@@ -0,0 +1,39 @@
1
+ #
2
+ # VariantDefault
3
+ #
4
+ # :: Class Methods
5
+ # :: Instance Methods
6
+
7
+ module Caboose
8
+ class VariantDefault < ActiveRecord::Base
9
+ self.table_name = 'store_variant_defaults'
10
+
11
+ belongs_to :site
12
+ attr_accessible :id ,
13
+ :site_id ,
14
+ :cost ,
15
+ :price ,
16
+ :available ,
17
+ :quantity_in_stock ,
18
+ :ignore_quantity ,
19
+ :allow_backorder ,
20
+ :weight ,
21
+ :length ,
22
+ :width ,
23
+ :height ,
24
+ :volume ,
25
+ :cylinder ,
26
+ :requires_shipping ,
27
+ :taxable ,
28
+ :shipping_unit_value ,
29
+ :flat_rate_shipping ,
30
+ :flat_rate_shipping_package_id ,
31
+ :flat_rate_shipping_method_id ,
32
+ :flat_rate_shipping_single ,
33
+ :flat_rate_shipping_combined ,
34
+ :status ,
35
+ :downloadable ,
36
+ :is_bundle
37
+
38
+ end
39
+ end
@@ -13,11 +13,12 @@
13
13
  <%= javascript_include_tag "caboose/admin_products" %>
14
14
  <% end %>
15
15
 
16
+ <div id='crumbtrail'></div>
16
17
  <h1 id="product-title">Edit Product - <%= @product.title %></h1>
17
18
  <ul id='tabs'>
18
19
  <%
19
20
  tabs = {
20
- "/admin/products/#{@product.id}/general" => 'Product details',
21
+ "/admin/products/#{@product.id}" => 'Product details',
21
22
  "/admin/products/#{@product.id}/description" => 'Long Description',
22
23
  "/admin/products/#{@product.id}/categories" => 'Categories'
23
24
  }
@@ -32,7 +33,8 @@ tabs["/admin/products/#{@product.id}/delete" ] = 'Delete Product'
32
33
 
33
34
  %>
34
35
  <% tabs.each do |href,text| %>
35
- <li<%= raw request.fullpath == href ? " class='selected'" : '' %>><a href='<%= href %>'><%= raw text %></a></li>
36
+ <% selected = href == "/admin/products/#{@product.id}" ? request.fullpath == href : request.fullpath.starts_with?(href) %>
37
+ <li<%= raw selected ? " class='selected'" : '' %>><a href='<%= href %>'><%= raw text %></a></li>
36
38
  <% end %>
37
39
  <li class='back'><input type='button' class="caboose-btn" value='< Back' onclick="window.location='/admin/products';" /></li>
38
40
  </ul>
@@ -19,6 +19,12 @@ label span.prefix { display: inline-block; margin: 0 8px; }
19
19
 
20
20
  var mb = false;
21
21
  $(document).ready(function() {
22
+
23
+ add_to_crumbtrail('/admin', 'Admin');
24
+ add_to_crumbtrail('/admin/products', 'Products');
25
+ add_to_crumbtrail('/admin/products/<%= p.id %>', <%= raw Caboose.json(p.title) %>);
26
+ add_to_crumbtrail('/admin/products/<%= p.id %>/categories', 'Categories');
27
+
22
28
  mb = new ModelBinder({
23
29
  name: 'Product',
24
30
  id: <%= p.id %>,
@@ -12,6 +12,12 @@ p = @product
12
12
  <script type='text/javascript'>
13
13
 
14
14
  $(document).ready(function() {
15
+
16
+ add_to_crumbtrail('/admin', 'Admin');
17
+ add_to_crumbtrail('/admin/products', 'Products');
18
+ add_to_crumbtrail('/admin/products/<%= p.id %>', <%= raw Caboose.json(p.title) %>);
19
+ add_to_crumbtrail('/admin/products/<%= p.id %>/description', 'Description');
20
+
15
21
  m = new ModelBinder({
16
22
  name: 'Product',
17
23
  id: <%= p.id %>,