caboose-cms 0.4.151 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (166) hide show
  1. checksums.yaml +8 -8
  2. data/app/assets/javascripts/caboose/admin_products.js +79 -0
  3. data/app/assets/javascripts/caboose/application.js +2 -1
  4. data/app/assets/javascripts/caboose/cart.js +168 -0
  5. data/app/assets/javascripts/caboose/checkout.js +151 -0
  6. data/app/assets/javascripts/caboose/checkout_module.js +312 -0
  7. data/app/assets/javascripts/caboose/checkout_step1.js +179 -0
  8. data/app/assets/javascripts/caboose/checkout_step2.js +39 -0
  9. data/app/assets/javascripts/caboose/checkout_step3.js +34 -0
  10. data/app/assets/javascripts/caboose/checkout_step4.js +97 -0
  11. data/app/assets/javascripts/caboose/main.js +99 -8
  12. data/app/assets/javascripts/caboose/product.js +284 -0
  13. data/app/assets/stylesheets/caboose/admin_products.css +86 -0
  14. data/app/assets/templates/caboose/cart/add_to_cart.jst.ejs +7 -0
  15. data/app/assets/templates/caboose/cart/line_items.jst.ejs +41 -0
  16. data/app/assets/templates/caboose/checkout/address.jst.ejs +53 -0
  17. data/app/assets/templates/caboose/checkout/forms/guest.jst.ejs +8 -0
  18. data/app/assets/templates/caboose/checkout/forms/register.jst.ejs +11 -0
  19. data/app/assets/templates/caboose/checkout/forms/signin.jst.ejs +7 -0
  20. data/app/assets/templates/caboose/checkout/line_items.jst.ejs +31 -0
  21. data/app/assets/templates/caboose/checkout/login.jst.ejs +21 -0
  22. data/app/assets/templates/caboose/checkout/payment.jst.ejs +5 -0
  23. data/app/assets/templates/caboose/checkout/shipping.jst.ejs +18 -0
  24. data/app/assets/templates/caboose/product/images.jst.ejs +8 -0
  25. data/app/assets/templates/caboose/product/options.jst.ejs +19 -0
  26. data/app/controllers/caboose/application_controller.rb +29 -1
  27. data/app/controllers/caboose/cart_controller.rb +52 -0
  28. data/app/controllers/caboose/categories_controller.rb +108 -0
  29. data/app/controllers/caboose/checkout_controller.rb +325 -0
  30. data/app/controllers/caboose/orders_controller.rb +439 -0
  31. data/app/controllers/caboose/product_images_controller.rb +38 -0
  32. data/app/controllers/caboose/products_controller.rb +737 -0
  33. data/app/controllers/caboose/reviews_controller.rb +15 -0
  34. data/app/controllers/caboose/variants_controller.rb +218 -0
  35. data/app/controllers/caboose/vendors_controller.rb +73 -0
  36. data/app/helpers/caboose/application_helper.rb +4 -0
  37. data/app/helpers/caboose/categories_helper.rb +82 -0
  38. data/app/helpers/caboose/checkout_helper.rb +20 -0
  39. data/app/helpers/caboose/products_helper.rb +8 -0
  40. data/app/mailers/caboose/orders_mailer.rb +30 -0
  41. data/app/models/caboose/address.rb +26 -0
  42. data/app/models/caboose/category.rb +89 -0
  43. data/app/models/caboose/category_membership.rb +10 -0
  44. data/app/models/caboose/core_plugin.rb +15 -37
  45. data/app/models/caboose/customization_membership.rb +10 -0
  46. data/app/models/caboose/discount.rb +16 -0
  47. data/app/models/caboose/line_item.rb +81 -0
  48. data/app/models/caboose/message.rb +20 -0
  49. data/app/models/caboose/order.rb +191 -0
  50. data/app/models/caboose/order_discount.rb +10 -0
  51. data/app/models/caboose/order_pdf.rb +78 -0
  52. data/app/models/caboose/payment_processors/authorizenet.rb +53 -0
  53. data/app/models/caboose/payment_processors/base.rb +39 -0
  54. data/app/models/caboose/payment_processors/payscape.rb +94 -0
  55. data/app/models/caboose/product.rb +145 -0
  56. data/app/models/caboose/product_image.rb +62 -0
  57. data/app/models/caboose/product_image_variant.rb +10 -0
  58. data/app/models/caboose/review.rb +13 -0
  59. data/app/models/caboose/schema.rb +205 -1
  60. data/app/models/caboose/search_filter.rb +191 -0
  61. data/app/models/caboose/shipping_calculator.rb +81 -0
  62. data/app/models/caboose/states.rb +61 -52
  63. data/app/models/caboose/tax_calculator.rb +23 -0
  64. data/app/models/caboose/tax_line.rb +9 -0
  65. data/app/models/caboose/variant.rb +99 -0
  66. data/app/models/caboose/vendor.rb +22 -0
  67. data/app/views/caboose/cart/index.html.erb +8 -0
  68. data/app/views/caboose/categories/admin_edit.html.erb +79 -0
  69. data/app/views/caboose/categories/admin_index.html.erb +11 -0
  70. data/app/views/caboose/categories/admin_new.html.erb +62 -0
  71. data/app/views/caboose/checkout/_address_form.html.erb +111 -0
  72. data/app/views/caboose/checkout/_billing_form.html.erb +47 -0
  73. data/app/views/caboose/checkout/_cart.html.erb +52 -0
  74. data/app/views/caboose/checkout/_confirm.html.erb +61 -0
  75. data/app/views/caboose/checkout/_order_discount.html.erb +40 -0
  76. data/app/views/caboose/checkout/_shipping_address.html.erb +10 -0
  77. data/app/views/caboose/checkout/_shipping_method.html.erb +2 -0
  78. data/app/views/caboose/checkout/_shipping_method_form.html.erb +21 -0
  79. data/app/views/caboose/checkout/billing.html.erb +11 -0
  80. data/app/views/caboose/checkout/discount.html.erb +11 -0
  81. data/app/views/caboose/checkout/empty.html.erb +2 -0
  82. data/app/views/caboose/checkout/error.html.erb +2 -0
  83. data/app/views/caboose/checkout/index.html.erb +43 -0
  84. data/app/views/caboose/checkout/login.html.erb +2 -0
  85. data/app/views/caboose/checkout/payment.html.erb +79 -0
  86. data/app/views/caboose/checkout/relay.html.erb +23 -0
  87. data/app/views/caboose/checkout/relay_old.html.erb +12 -0
  88. data/app/views/caboose/checkout/relay_postMessage.html.erb +19 -0
  89. data/app/views/caboose/checkout/shipping.html.erb +15 -0
  90. data/app/views/caboose/checkout/step_four.html.erb +93 -0
  91. data/app/views/caboose/checkout/step_one.html.erb +56 -0
  92. data/app/views/caboose/checkout/step_one_old.html.erb +13 -0
  93. data/app/views/caboose/checkout/step_three.html.erb +23 -0
  94. data/app/views/caboose/checkout/step_two.html.erb +52 -0
  95. data/app/views/caboose/checkout/step_two_old.html.erb +14 -0
  96. data/app/views/caboose/checkout/thanks.html.erb +5 -0
  97. data/app/views/caboose/orders/_admin_footer.html.erb +2 -0
  98. data/app/views/caboose/orders/_admin_header.html.erb +31 -0
  99. data/app/views/caboose/orders/_quickbooks_order.html.erb +0 -0
  100. data/app/views/caboose/orders/admin_delete_form.html.erb +21 -0
  101. data/app/views/caboose/orders/admin_edit.html.erb +271 -0
  102. data/app/views/caboose/orders/admin_index.html.erb +89 -0
  103. data/app/views/caboose/orders/admin_new.html.erb +42 -0
  104. data/app/views/caboose/orders/admin_print.html.erb +72 -0
  105. data/app/views/caboose/orders_mailer/customer_new_order.html.erb +1 -0
  106. data/app/views/caboose/orders_mailer/customer_status_updated.html.erb +1 -0
  107. data/app/views/caboose/orders_mailer/fulfillment_new_order.html.erb +1 -0
  108. data/app/views/caboose/orders_mailer/shipping_order_ready.html.erb +1 -0
  109. data/app/views/caboose/products/_admin_footer.html.erb +2 -0
  110. data/app/views/caboose/products/_admin_header.html.erb +32 -0
  111. data/app/views/caboose/products/_sort_options.html.erb +19 -0
  112. data/app/views/caboose/products/admin_add_upcs.html.erb +58 -0
  113. data/app/views/caboose/products/admin_delete_form.html.erb +21 -0
  114. data/app/views/caboose/products/admin_edit_categories.html.erb +73 -0
  115. data/app/views/caboose/products/admin_edit_category_images.html.erb +233 -0
  116. data/app/views/caboose/products/admin_edit_description.html.erb +38 -0
  117. data/app/views/caboose/products/admin_edit_general.html.erb +104 -0
  118. data/app/views/caboose/products/admin_edit_images.html.erb +236 -0
  119. data/app/views/caboose/products/admin_edit_options.html.erb +51 -0
  120. data/app/views/caboose/products/admin_edit_seo.html.erb +37 -0
  121. data/app/views/caboose/products/admin_edit_variant_columns.html.erb +75 -0
  122. data/app/views/caboose/products/admin_edit_variant_sort_order.html.erb +63 -0
  123. data/app/views/caboose/products/admin_edit_variants.html.erb +171 -0
  124. data/app/views/caboose/products/admin_edit_variants_single.html.erb +68 -0
  125. data/app/views/caboose/products/admin_group_variants.html.erb +433 -0
  126. data/app/views/caboose/products/admin_index.html.erb +95 -0
  127. data/app/views/caboose/products/admin_new.html.erb +41 -0
  128. data/app/views/caboose/products/admin_sort.html copy.erb +155 -0
  129. data/app/views/caboose/products/admin_sort.html.erb +254 -0
  130. data/app/views/caboose/products/details.html.erb +438 -0
  131. data/app/views/caboose/products/index.html.erb +46 -0
  132. data/app/views/caboose/products/not_available.html.erb +35 -0
  133. data/app/views/caboose/variants/admin_edit.html.erb +82 -0
  134. data/app/views/caboose/variants/admin_group.html.erb +184 -0
  135. data/app/views/caboose/variants/admin_new.html.erb +59 -0
  136. data/app/views/caboose/vendors/admin_edit.html.erb +24 -0
  137. data/app/views/caboose/vendors/admin_index.html.erb +30 -0
  138. data/app/views/caboose/vendors/admin_new.html.erb +34 -0
  139. data/app/views/layouts/caboose/store/_banner.html.erb +10 -0
  140. data/app/views/layouts/caboose/store/_banner2.html.erb +10 -0
  141. data/app/views/layouts/caboose/store/_footer.html.erb +55 -0
  142. data/app/views/layouts/caboose/store/_header.html.erb +69 -0
  143. data/app/views/layouts/caboose/store/_sidebar.html.erb +27 -0
  144. data/app/views/layouts/caboose/store/application.html.erb +33 -0
  145. data/app/views/layouts/caboose/store/authorize_net.erb +18 -0
  146. data/app/views/layouts/caboose/store/layout_about.html.erb +42 -0
  147. data/app/views/layouts/caboose/store/layout_blog.html.erb +159 -0
  148. data/app/views/layouts/caboose/store/layout_confirm.html.erb +85 -0
  149. data/app/views/layouts/caboose/store/layout_contact.html.erb +38 -0
  150. data/app/views/layouts/caboose/store/layout_default.html.erb +10 -0
  151. data/app/views/layouts/caboose/store/layout_detail.html.erb +114 -0
  152. data/app/views/layouts/caboose/store/layout_order.html.erb +77 -0
  153. data/app/views/layouts/caboose/store/layout_pricing.html.erb +182 -0
  154. data/app/views/layouts/caboose/store/layout_product.html.erb +110 -0
  155. data/app/views/layouts/caboose/store/layout_profile.html.erb +55 -0
  156. data/app/views/layouts/caboose/store/layout_single.html.erb +3 -0
  157. data/app/views/layouts/caboose/store/layout_testimonial.html.erb +110 -0
  158. data/app/views/layouts/caboose/store/layout_testing.html.erb +4 -0
  159. data/config/routes.rb +126 -0
  160. data/lib/caboose.rb +46 -1
  161. data/lib/caboose/engine.rb +39 -1
  162. data/lib/caboose/version.rb +1 -1
  163. data/lib/tasks/caboose.rake +12 -0
  164. metadata +151 -4
  165. data/app/assets/javascripts/caboose/admin_page_edit_content_bak.js +0 -164
  166. data/app/assets/javascripts/caboose/model/#Untitled-1# +0 -2
@@ -0,0 +1,737 @@
1
+ module Caboose
2
+ PageBarGenerator.class_eval do
3
+ def all_records
4
+ return model_with_includes.where(where)
5
+ end
6
+ end
7
+ end
8
+
9
+ module Caboose
10
+ class ProductsController < Caboose::ApplicationController
11
+
12
+ # GET /products || GET /products/:id
13
+ def index
14
+
15
+ # If id exists, is an integer and a product exists with the specified id then get the product
16
+ if params[:id] && params[:id].to_i > 0 && Product.exists?(params[:id])
17
+ @product = Product.find(params[:id])
18
+ render 'product/not_available' and return if @product.status == 'Inactive'
19
+
20
+ @category = @product.categories.first
21
+ @review = Review.new
22
+ @reviews = Review.where(:product_id => @product.id).limit(10).order("id DESC") || nil
23
+ @logged_in_user = logged_in_user
24
+
25
+ render 'caboose/products/details' and return
26
+ end
27
+
28
+ # Filter params from url
29
+ url_without_params = request.fullpath.split('?').first
30
+
31
+ # Find the category
32
+ category = Category.where(:url => url_without_params).first
33
+
34
+ # Set category ID
35
+ params['category_id'] = category.id
36
+
37
+ # If this is the top-most category, collect all it's immediate children IDs
38
+ params['category_id'] = category.children.collect { |child| child.id } if category.id == 1
39
+
40
+ # Shove the original category ID into the first position if the param is an array
41
+ params['category_id'].unshift(category.id) if params['category_id'].is_a?(Array)
42
+
43
+ # Otherwise looking at a category or search parameters
44
+ @pager = Caboose::Pager.new(params, {
45
+ 'category_id' => '',
46
+ 'vendor_id' => '',
47
+ 'vendor_name' => '',
48
+ 'vendor_status' => 'Active',
49
+ 'status' => 'Active',
50
+ 'variant_status' => 'Active',
51
+ 'price_gte' => '',
52
+ 'price_lte' => '',
53
+ 'alternate_id' => '',
54
+ 'search_like' => ''
55
+ }, {
56
+ 'model' => 'Caboose::Product',
57
+ 'sort' => if params[:sort] then params[:sort] else 'store_products.sort_order' end,
58
+ 'base_url' => url_without_params,
59
+ 'items_per_page' => 15,
60
+ 'use_url_params' => false,
61
+
62
+ 'abbreviations' => {
63
+ 'search_like' => 'title_concat_store_products.alternate_id_concat_vendor_name_concat_category_name_like',
64
+ },
65
+
66
+ 'includes' => {
67
+ 'category_id' => [ 'categories' , 'id' ],
68
+ 'category_name' => [ 'categories' , 'name' ],
69
+ 'vendor_id' => [ 'vendor' , 'id' ],
70
+ 'vendor_name' => [ 'vendor' , 'name' ],
71
+ 'vendor_status' => [ 'vendor' , 'status' ],
72
+ 'price_gte' => [ 'variants' , 'price' ],
73
+ 'price_lte' => [ 'variants' , 'price' ],
74
+ 'variant_status' => [ 'variants' , 'status' ]
75
+ }
76
+ })
77
+
78
+ @sort_options = [
79
+ { :name => 'Default', :value => 'store_products.sort_order' },
80
+ { :name => 'Price (Low to High)', :value => 'store_variants.price ASC' },
81
+ { :name => 'Price (High to Low)', :value => 'store_variants.price DESC' },
82
+ { :name => 'Alphabetical (A-Z)', :value => 'store_products.title ASC' },
83
+ { :name => 'Alphabetical (Z-A)', :value => 'store_products.title DESC' },
84
+ ]
85
+
86
+ SearchFilter.delete_all
87
+
88
+ @filter = SearchFilter.find_from_url(request.fullpath, @pager, ['page'])
89
+ @products = @pager.items
90
+ @category = if @filter['category_id'] then Category.find(@filter['category_id'].to_i) else nil end
91
+
92
+ @pager.set_item_count
93
+ end
94
+
95
+ def show
96
+ end
97
+
98
+ # GET /product/info
99
+ def info
100
+ p = Product.find(params[:id])
101
+ render :json => {
102
+ :product => p,
103
+ :option1_values => p.option1_values,
104
+ :option2_values => p.option2_values,
105
+ :option3_values => p.option3_values
106
+ }
107
+ end
108
+
109
+ # GET /api/products
110
+ def api_list
111
+ render :json => Product.where(:status => 'Active')
112
+ end
113
+
114
+ # GET /api/products/:id
115
+ def api_details
116
+ render :json => Product.find(params[:id])
117
+ end
118
+
119
+ # GET /api/products/:id/variants
120
+ def api_variants
121
+ render :json => Product.find(params[:id]).variants
122
+ end
123
+
124
+ #=============================================================================
125
+ # Admin actions
126
+ #=============================================================================
127
+
128
+ # GET /admin/products/:id/variants/group
129
+ def admin_group_variants
130
+ @product = Product.find(params[:id])
131
+
132
+ return if !user_is_allowed('variants', 'edit')
133
+
134
+ joins = []
135
+ where = []
136
+ values = []
137
+
138
+ if params[:category_ids]
139
+ joins << [:category_memberships]
140
+ where << 'store_category_memberships.category_id IN (?)'
141
+ values << params[:category_ids]
142
+ end
143
+
144
+ if params[:vendor_ids]
145
+ joins << [:vendor]
146
+ where << 'store_vendors.id IN (?)'
147
+ values << params[:vendor_ids]
148
+ end
149
+
150
+ if params[:title]
151
+ where << 'LOWER(store_products.title) LIKE ?'
152
+ values << "%#{params[:title].downcase}%"
153
+ end
154
+
155
+ # Query for all relevant products
156
+ products = values.any? ? Product.joins(joins).where([where.join(' AND ')].concat(values)) : []
157
+
158
+ # Grab variants for each product
159
+ @variants = products.collect { |product| product.variants }.flatten
160
+
161
+ # Grab all categories; except for "all" and "uncategorized"
162
+ @categories = Category.where('parent_id IS NOT NULL AND name IS NOT NULL').order(:url)
163
+
164
+ # Grab all vendors
165
+ @vendors = Vendor.where('name IS NOT NULL').order(:name)
166
+
167
+ render :layout => 'caboose/admin'
168
+ end
169
+
170
+ # POST /admin/products/:id/variants/add
171
+ def admin_add_variants
172
+ params[:variant_ids].each do |variant_id|
173
+ variant = Variant.find(variant_id)
174
+
175
+ # Delete current variant product if this is the last variant
176
+ # variant.product.update_attribute(:status, 'deleted') if variant.product.variants.where('status != ?', 'deleted').count == 0
177
+
178
+ # Add reference to new product
179
+ # varant.product_id = params[:id]
180
+ end
181
+
182
+ # Iterate over variants and add them to the product
183
+ # Remove product that the variants are associated with; UNLESS it's the current product
184
+
185
+ redirect_to "/admin/products/#{params[:id]}/variants"
186
+ end
187
+
188
+ # POST /admin/products/:id/varaints/add-multiple
189
+ def admin_add_multiple_variants
190
+ product = Product.find(params[:id])
191
+
192
+ params[:variants_csv].split("\r\n").each do |variant|
193
+ row = variant.split(',')
194
+
195
+ render :json => { :success => false, :error => "Quantity is not defined for variant: #{row[0].strip}" } and return if row[1].nil?
196
+ render :json => { :success => false, :error => "Price is not defined for variant: #{row[0].strip}" } and return if row[2].nil?
197
+
198
+ attributes = {
199
+ :alternate_id => row[0].strip,
200
+ :quantity_in_stock => row[1].strip.to_i,
201
+ :price => '%.2f' % row[2].strip.to_f,
202
+ :status => 'Active'
203
+ }
204
+
205
+ if product.option1 && row[3].nil?
206
+ render :json => { :success => false, :error => "#{product.option1} not defined for variant: #{attributes[:alternate_id]}" } and return
207
+ elsif product.option1
208
+ attributes[:option1] = row[3].strip
209
+ end
210
+
211
+ if product.option2 && row[4].nil?
212
+ render :json => { :success => false, :error => "#{product.option2} not defined for variant: #{attributes[:alternate_id]}" } and return
213
+ elsif product.option2
214
+ attributes[:option2] = row[4].strip
215
+ end
216
+
217
+ if product.option3 && row[5].nil?
218
+ render :json => { :success => false, :error => "#{product.option3} not defined for variant: #{attributes[:alternate_id]}" } and return
219
+ elsif product.option3
220
+ attributes[:option3] = row[5].strip
221
+ end
222
+
223
+ if product.variants.find_by_alternate_id(attributes[:alternate_id])
224
+ product.variants.find_by_alternate_id(attributes[:alternate_id]).update_attributes(attributes)
225
+ else
226
+ Variant.create(attributes.merge(:product_id => product.id))
227
+ end
228
+ end
229
+
230
+ render :json => { :success => true }
231
+ end
232
+
233
+ # POST /admin//products/:id/variants/remove
234
+ def admin_remove_variants
235
+ params[:variant_ids].each do |variant_id|
236
+ variant = Variant.find(variant_id)
237
+ # variant.update_attribute(:status, 'deleted')
238
+ # variant.product.update_attribute(:status, 'deleted') if variant.product.variants.where('status != ?', 'deleted').count == 0
239
+ end
240
+
241
+ # Remove passed variants
242
+ # redirect_to "/admin/products/#{params[:id]}/variants/group"
243
+
244
+ render :json => true
245
+ end
246
+
247
+ # GET /admin/products/update-vendor-status/:id
248
+ def admin_update_vendor_status
249
+ vendor = Vendor.find(params[:id])
250
+ vendor.status = params[:status]
251
+ render :json => vendor.save
252
+ end
253
+
254
+ # GET /admin/products
255
+ def admin_index
256
+ return if !user_is_allowed('products', 'view')
257
+
258
+ # Temporary patch for vendor name sorting; Fix this
259
+ params[:sort] = 'store_vendors.name' if params[:sort] == 'vendor'
260
+
261
+ @gen = Caboose::PageBarGenerator.new(params, {
262
+ 'vendor_name' => '',
263
+ 'search_like' => '',
264
+ 'price' => params[:filters] && params[:filters][:missing_prices] ? 0 : ''
265
+ }, {
266
+ 'model' => 'Caboose::Product',
267
+ 'sort' => 'title',
268
+ 'desc' => false,
269
+ 'base_url' => '/admin/products',
270
+ 'items_per_page' => 25,
271
+ 'use_url_params' => false,
272
+
273
+ 'abbreviations' => {
274
+ 'search_like' => 'store_products.title_concat_vendor_name_like'
275
+ },
276
+
277
+ 'includes' => {
278
+ 'vendor_name' => [ 'vendor' , 'name' ],
279
+ 'price' => [ 'variants' , 'price' ]
280
+ }
281
+ })
282
+
283
+ # Make a copy of all the items; so it can be filtered more
284
+ @all_products = @gen.all_records
285
+
286
+ # Apply any extra filters
287
+ if params[:filters]
288
+ @all_products = @all_products.includes(:product_images).where('store_product_images.id IS NULL') if params[:filters][:missing_images]
289
+ @all_products = @all_products.where('vendor_id IS NULL') if params[:filters][:no_vendor]
290
+ end
291
+
292
+ # Get the correct page of the results
293
+ @products = @all_products.limit(@gen.limit).offset(@gen.offset)
294
+
295
+ render :layout => 'caboose/admin'
296
+ end
297
+
298
+ # GET /admin/products/add-upcs - TODO remove this; it's a temporary thing for woods-n-water
299
+ def admin_add_upcs
300
+ params[:vendor_id] if params[:vendor_id] and params[:vendor_id].empty?
301
+
302
+ conditions = if params[:vendor_id]
303
+ "store_variants.alternate_id IS NULL and store_vendors.id = #{params[:vendor_id]}"
304
+ else
305
+ "store_variants.alternate_id IS NULL"
306
+ end
307
+
308
+ @products = Product.all(
309
+ :include => [:variants, :vendor],
310
+ :conditions => conditions
311
+ )
312
+
313
+ render :layout => 'caboose/admin'
314
+ end
315
+
316
+ # GET /admin/products/:id/general
317
+ def admin_edit_general
318
+ return if !user_is_allowed('products', 'edit')
319
+ @product = Product.find(params[:id])
320
+ render :layout => 'caboose/admin'
321
+ end
322
+
323
+ # GET /admin/products/:id/description
324
+ def admin_edit_description
325
+ return if !user_is_allowed('products', 'edit')
326
+ @product = Product.find(params[:id])
327
+ render :layout => 'caboose/admin'
328
+ end
329
+
330
+ # GET /admin/products/:id/variants
331
+ # GET /admin/products/:id/variants/:variant_id
332
+ def admin_edit_variants
333
+ return if !user_is_allowed('products', 'edit')
334
+ @product = Product.find(params[:id])
335
+
336
+ if @product.variants.nil? || @product.variants.count == 0
337
+ v = Variant.new
338
+ v.option1 = @product.default1 if @product.option1
339
+ v.option2 = @product.default2 if @product.option2
340
+ v.option3 = @product.default3 if @product.option3
341
+ v.status = 'Active'
342
+ @product.variants = [v]
343
+ @product.save
344
+ end
345
+ @variant = params[:variant_id] ? Variant.find(params[:variant_id]) : @product.variants[0]
346
+ session['variant_cols'] = self.default_variant_cols if session['variant_cols'].nil?
347
+ @cols = session['variant_cols']
348
+
349
+ @highlight_variant_id = params[:highlight] ? params[:highlight].to_i : nil
350
+
351
+ if @product.options.nil? || @product.options.count == 0
352
+ render 'caboose/products/admin_edit_variants_single', :layout => 'caboose/admin'
353
+ else
354
+ render 'caboose/products/admin_edit_variants', :layout => 'caboose/admin'
355
+ end
356
+ end
357
+
358
+ # GET /admin/products/:id/variants/json
359
+ def admin_variants_json
360
+ render :json => false if !user_is_allowed('products', 'edit')
361
+ p = Product.find(params[:id])
362
+ render :json => p.variants
363
+ end
364
+
365
+ # GET /admin/products/:id/variant-cols
366
+ def admin_edit_variant_columns
367
+ return if !user_is_allowed('products', 'edit')
368
+ @product = Product.find(params[:id])
369
+ session['variant_cols'] = self.default_variant_cols if session['variant_cols'].nil?
370
+ @cols = session['variant_cols']
371
+ render :layout => 'caboose/admin'
372
+ end
373
+
374
+ # PUT /admin/products/:id/variant-cols
375
+ def admin_update_variant_columns
376
+ return if !user_is_allowed('products', 'edit')
377
+ session['variant_cols'] = self.default_variant_cols if session['variant_cols'].nil?
378
+
379
+ resp = Caboose::StdClass.new({'attributes' => {}})
380
+ product = Product.find(params[:id])
381
+
382
+ save = true
383
+ params.each do |name,value|
384
+ value = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
385
+ case name
386
+ when 'option1' ,
387
+ 'option2' ,
388
+ 'option3' ,
389
+ 'status' ,
390
+ 'alternate_id' ,
391
+ 'sku' ,
392
+ 'barcode' ,
393
+ 'price' ,
394
+ 'quantity_in_stock' ,
395
+ 'weight' ,
396
+ 'length' ,
397
+ 'width' ,
398
+ 'height' ,
399
+ 'cylinder' ,
400
+ 'requires_shipping' ,
401
+ 'allow_backorder' ,
402
+ 'taxable'
403
+ session['variant_cols'][name] = value
404
+ end
405
+ end
406
+ resp.success = save && product.save
407
+ render :json => resp
408
+ end
409
+
410
+ def default_variant_cols
411
+ return {
412
+ 'option1' => true,
413
+ 'option2' => true,
414
+ 'option3' => true,
415
+ 'status' => true,
416
+ 'alternate_id' => true,
417
+ 'sku' => true,
418
+ 'barcode' => false,
419
+ 'price' => true,
420
+ 'quantity' => true,
421
+ 'weight' => false,
422
+ 'length' => false,
423
+ 'width' => false,
424
+ 'height' => false,
425
+ 'cylinder' => false,
426
+ 'requires_shipping' => false,
427
+ 'allow_backorder' => false,
428
+ 'taxable' => false
429
+ }
430
+ end
431
+
432
+ # GET /admin/products/:id/options
433
+ def admin_edit_options
434
+ return if !user_is_allowed('products', 'edit')
435
+ @product = Product.find(params[:id])
436
+ render :layout => 'caboose/admin'
437
+ end
438
+
439
+ # GET /admin/products/:id/categories
440
+ def admin_edit_categories
441
+ return if !user_is_allowed('products', 'edit')
442
+ @product = Product.find(params[:id])
443
+ @top_categories = Category.where(:parent_id => 1).reorder('name').all
444
+ @selected_ids = @product.categories.collect{ |cat| cat.id }
445
+ render :layout => 'caboose/admin'
446
+ end
447
+
448
+ # POST /admin/products/:id/categories
449
+ def admin_add_to_category
450
+ return if !user_is_allowed('products', 'edit')
451
+ cat_id = params[:category_id]
452
+ product_id = params[:id]
453
+
454
+ if !CategoryMembership.exists?(:category_id => cat_id, :product_id => product_id)
455
+ CategoryMembership.create(:category_id => cat_id, :product_id => product_id)
456
+ end
457
+ render :json => true
458
+ end
459
+
460
+ # DELETE /admin/products/:id/categories/:category_id
461
+ def admin_remove_from_category
462
+ return if !user_is_allowed('products', 'edit')
463
+ cat_id = params[:category_id]
464
+ product_id = params[:id]
465
+
466
+ if CategoryMembership.exists?(:category_id => cat_id, :product_id => product_id)
467
+ CategoryMembership.where(:category_id => cat_id, :product_id => product_id).destroy_all
468
+ end
469
+ render :json => true
470
+ end
471
+
472
+ # GET /admin/products/:id/images
473
+ def admin_edit_images
474
+ return if !user_is_allowed('products', 'edit')
475
+ @product = Product.find(params[:id])
476
+ render :layout => 'caboose/admin'
477
+ end
478
+
479
+ # POST /admin/products/:id/images
480
+ def admin_add_image
481
+ return if !user_is_allowed('products', 'edit')
482
+ product_id = params[:id]
483
+
484
+ if (params[:new_image].nil?)
485
+ render :text => "<script type='text/javascript'>parent.modal.autosize(\"<p class='note error'>You must provide an image.</p>\", 'new_image_message');</script>"
486
+ else
487
+ img = ProductImage.new
488
+ img.product_id = product_id
489
+ img.image = params[:new_image]
490
+ img.square_offset_x = 0
491
+ img.square_offset_y = 0
492
+ img.square_scale_factor = 1.00
493
+ img.save
494
+ render :text => "<script type='text/javascript'>parent.window.location.reload(true);</script>"
495
+ end
496
+ end
497
+
498
+ # GET /admin/products/:id/collections
499
+ def admin_edit_collections
500
+ return if !user_is_allowed('products', 'edit')
501
+ @product = Product.find(params[:id])
502
+ render :layout => 'caboose/admin'
503
+ end
504
+
505
+ # GET /admin/products/:id/seo
506
+ def admin_edit_seo
507
+ return if !user_is_allowed('products', 'edit')
508
+ @product = Product.find(params[:id])
509
+ render :layout => 'caboose/admin'
510
+ end
511
+
512
+ # GET /admin/products/:id/variants/sort-order
513
+ def admin_edit_variant_sort_order
514
+ return if !user_is_allowed('products', 'edit')
515
+ @product = Product.find(params[:id])
516
+ render :layout => 'caboose/admin'
517
+ end
518
+
519
+ # GET /admin/products/:id/delete
520
+ def admin_delete_form
521
+ return if !user_is_allowed('products', 'edit')
522
+ @product = Product.find(params[:id])
523
+ render :layout => 'caboose/admin'
524
+ end
525
+
526
+ # PUT /admin/products/:id
527
+ def admin_update
528
+ return if !user_is_allowed('products', 'edit')
529
+
530
+ resp = Caboose::StdClass.new({'attributes' => {}})
531
+ product = Product.find(params[:id])
532
+
533
+ save = true
534
+ params.each do |name,value|
535
+ case name
536
+ when 'alternate_id'
537
+ product.alternate_id = value
538
+ when 'date_available'
539
+ if value.strip.length == 0
540
+ product.date_available = nil
541
+ else
542
+ begin
543
+ product.date_available = DateTime.parse(value)
544
+ rescue
545
+ resp.error = "Invalid date"
546
+ save = false
547
+ end
548
+ end
549
+ when 'title'
550
+ product.title = value
551
+ when 'caption'
552
+ product.caption = value
553
+ when 'featured'
554
+ product.featured = value
555
+ when 'description'
556
+ product.description = value
557
+ when 'category_id'
558
+ product.category_id = value
559
+ when 'vendor_id'
560
+ product.vendor_id = value
561
+ when 'handle'
562
+ product.handle = value
563
+ when 'seo_title'
564
+ product.seo_title = value
565
+ when 'seo_description'
566
+ product.seo_description = value
567
+ when 'option1'
568
+ product.option1 = value
569
+ when 'option2'
570
+ product.option2 = value
571
+ when 'option3'
572
+ product.option3 = value
573
+ when 'default1'
574
+ product.default1 = value
575
+ Variant.where(:product_id => product.id, :option1 => nil).each do |p|
576
+ p.option1 = value
577
+ p.save
578
+ end
579
+ when 'default2'
580
+ product.default2 = value
581
+ Variant.where(:product_id => product.id, :option2 => nil).each do |p|
582
+ p.option2 = value
583
+ p.save
584
+ end
585
+ when 'default3'
586
+ product.default3 = value
587
+ Variant.where(:product_id => product.id, :option3 => nil).each do |p|
588
+ p.option3 = value
589
+ p.save
590
+ end
591
+ when 'status'
592
+ product.status = value
593
+ end
594
+ end
595
+ resp.success = save && product.save
596
+ render :json => resp
597
+ end
598
+
599
+ # GET /admin/products/new
600
+ def admin_new
601
+ return if !user_is_allowed('products', 'add')
602
+ render :layout => 'caboose/admin'
603
+ end
604
+
605
+ # POST /admin/products
606
+ def admin_add
607
+ return if !user_is_allowed('products', 'add')
608
+
609
+ resp = Caboose::StdClass.new(
610
+ :error => nil,
611
+ :redirect => nil
612
+ )
613
+
614
+ title = params[:title]
615
+
616
+ if title.length == 0
617
+ resp.error = "The title cannot be empty."
618
+ else
619
+ p = Product.new(:title => title)
620
+ p.save
621
+ resp.redirect = "/admin/products/#{p.id}/general"
622
+ end
623
+ render :json => resp
624
+ end
625
+
626
+ # DELETE /admin/products/:id
627
+ def admin_delete
628
+ return if !user_is_allowed('products', 'delete')
629
+ p = Product.find(params[:id]).destroy
630
+ p.status = 'Deleted'
631
+ p.save
632
+ render :json => Caboose::StdClass.new({
633
+ :redirect => '/admin/products'
634
+ })
635
+ end
636
+
637
+ # GET /products/status-options
638
+ def admin_status_options
639
+ arr = ['Active', 'Inactive', 'Deleted']
640
+ options = []
641
+ arr.each do |status|
642
+ options << {
643
+ :value => status,
644
+ :text => status
645
+ }
646
+ end
647
+ render :json => options
648
+ end
649
+
650
+ # GET /admin/products/combine
651
+ def admin_combine_select_products
652
+ end
653
+
654
+ # GET /admin/products/combine-step2
655
+ def admin_combine_assign_title
656
+ end
657
+
658
+ # POST /admin/products/combine
659
+ def admin_combine
660
+ product_ids = params[:product_ids]
661
+
662
+ p = Product.new
663
+ p.title = params[:title]
664
+ p.description = params[:description]
665
+ p.option1 = params[:option1]
666
+ p.option2 = params[:option2]
667
+ p.option3 = params[:option3]
668
+ p.default1 = params[:default1]
669
+ p.default2 = params[:default2]
670
+ p.default3 = params[:default3]
671
+ p.status = 'Active'
672
+ p.save
673
+
674
+ product_ids.each do |pid|
675
+ p = Product.find(pid)
676
+ p.variants.each do |v|
677
+ end
678
+ end
679
+ end
680
+
681
+ # PUT /admin/products/:id/update-vendor
682
+ def admin_update_vendor
683
+ render :json => { :success => Product.find(params[:id]).update_attribute(:vendor_id, params[:vendor_id]) }
684
+ end
685
+
686
+ # GET /admin/products/sort
687
+ def admin_sort
688
+ @products = Product.active
689
+ @vendors = Vendor.active
690
+ @categories = Category.all
691
+
692
+ render :layout => 'caboose/admin'
693
+ end
694
+
695
+ # PUT /admin/products/update-sort-order
696
+ def admin_update_sort_order
697
+ params[:product_ids].each_with_index do |product_id, index|
698
+ Product.find(product_id.to_i).update_attribute(:sort_order, index)
699
+ end
700
+ render :json => { :success => true }
701
+ end
702
+
703
+ # PUT /admin/products/:id/variants/option1-sort-order
704
+ def admin_update_variant_option1_sort_order
705
+ product_id = params[:id]
706
+ params[:values].each_with_index do |value, i|
707
+ Variant.where(:product_id => product_id, :option1 => value).all.each do |v|
708
+ v.update_attribute(:option1_sort_order, i)
709
+ end
710
+ end
711
+ render :json => { :success => true }
712
+ end
713
+
714
+ # PUT /admin/products/:id/variants/option1-sort-order
715
+ def admin_update_variant_option2_sort_order
716
+ product_id = params[:id]
717
+ params[:values].each_with_index do |value, i|
718
+ Variant.where(:product_id => product_id, :option2 => value).all.each do |v|
719
+ v.update_attribute(:option2_sort_order, i)
720
+ end
721
+ end
722
+ render :json => { :success => true }
723
+ end
724
+
725
+ # PUT /admin/products/:id/variants/option1-sort-order
726
+ def admin_update_variant_option3_sort_order
727
+ product_id = params[:id]
728
+ params[:values].each_with_index do |value, i|
729
+ Variant.where(:product_id => product_id, :option3 => value).all.each do |v|
730
+ v.update_attribute(:option3_sort_order, i)
731
+ end
732
+ end
733
+ render :json => { :success => true }
734
+ end
735
+ end
736
+ end
737
+