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.
- checksums.yaml +8 -8
- data/app/assets/javascripts/caboose/admin_products.js +79 -0
- data/app/assets/javascripts/caboose/application.js +2 -1
- data/app/assets/javascripts/caboose/cart.js +168 -0
- data/app/assets/javascripts/caboose/checkout.js +151 -0
- data/app/assets/javascripts/caboose/checkout_module.js +312 -0
- data/app/assets/javascripts/caboose/checkout_step1.js +179 -0
- data/app/assets/javascripts/caboose/checkout_step2.js +39 -0
- data/app/assets/javascripts/caboose/checkout_step3.js +34 -0
- data/app/assets/javascripts/caboose/checkout_step4.js +97 -0
- data/app/assets/javascripts/caboose/main.js +99 -8
- data/app/assets/javascripts/caboose/product.js +284 -0
- data/app/assets/stylesheets/caboose/admin_products.css +86 -0
- data/app/assets/templates/caboose/cart/add_to_cart.jst.ejs +7 -0
- data/app/assets/templates/caboose/cart/line_items.jst.ejs +41 -0
- data/app/assets/templates/caboose/checkout/address.jst.ejs +53 -0
- data/app/assets/templates/caboose/checkout/forms/guest.jst.ejs +8 -0
- data/app/assets/templates/caboose/checkout/forms/register.jst.ejs +11 -0
- data/app/assets/templates/caboose/checkout/forms/signin.jst.ejs +7 -0
- data/app/assets/templates/caboose/checkout/line_items.jst.ejs +31 -0
- data/app/assets/templates/caboose/checkout/login.jst.ejs +21 -0
- data/app/assets/templates/caboose/checkout/payment.jst.ejs +5 -0
- data/app/assets/templates/caboose/checkout/shipping.jst.ejs +18 -0
- data/app/assets/templates/caboose/product/images.jst.ejs +8 -0
- data/app/assets/templates/caboose/product/options.jst.ejs +19 -0
- data/app/controllers/caboose/application_controller.rb +29 -1
- data/app/controllers/caboose/cart_controller.rb +52 -0
- data/app/controllers/caboose/categories_controller.rb +108 -0
- data/app/controllers/caboose/checkout_controller.rb +325 -0
- data/app/controllers/caboose/orders_controller.rb +439 -0
- data/app/controllers/caboose/product_images_controller.rb +38 -0
- data/app/controllers/caboose/products_controller.rb +737 -0
- data/app/controllers/caboose/reviews_controller.rb +15 -0
- data/app/controllers/caboose/variants_controller.rb +218 -0
- data/app/controllers/caboose/vendors_controller.rb +73 -0
- data/app/helpers/caboose/application_helper.rb +4 -0
- data/app/helpers/caboose/categories_helper.rb +82 -0
- data/app/helpers/caboose/checkout_helper.rb +20 -0
- data/app/helpers/caboose/products_helper.rb +8 -0
- data/app/mailers/caboose/orders_mailer.rb +30 -0
- data/app/models/caboose/address.rb +26 -0
- data/app/models/caboose/category.rb +89 -0
- data/app/models/caboose/category_membership.rb +10 -0
- data/app/models/caboose/core_plugin.rb +15 -37
- data/app/models/caboose/customization_membership.rb +10 -0
- data/app/models/caboose/discount.rb +16 -0
- data/app/models/caboose/line_item.rb +81 -0
- data/app/models/caboose/message.rb +20 -0
- data/app/models/caboose/order.rb +191 -0
- data/app/models/caboose/order_discount.rb +10 -0
- data/app/models/caboose/order_pdf.rb +78 -0
- data/app/models/caboose/payment_processors/authorizenet.rb +53 -0
- data/app/models/caboose/payment_processors/base.rb +39 -0
- data/app/models/caboose/payment_processors/payscape.rb +94 -0
- data/app/models/caboose/product.rb +145 -0
- data/app/models/caboose/product_image.rb +62 -0
- data/app/models/caboose/product_image_variant.rb +10 -0
- data/app/models/caboose/review.rb +13 -0
- data/app/models/caboose/schema.rb +205 -1
- data/app/models/caboose/search_filter.rb +191 -0
- data/app/models/caboose/shipping_calculator.rb +81 -0
- data/app/models/caboose/states.rb +61 -52
- data/app/models/caboose/tax_calculator.rb +23 -0
- data/app/models/caboose/tax_line.rb +9 -0
- data/app/models/caboose/variant.rb +99 -0
- data/app/models/caboose/vendor.rb +22 -0
- data/app/views/caboose/cart/index.html.erb +8 -0
- data/app/views/caboose/categories/admin_edit.html.erb +79 -0
- data/app/views/caboose/categories/admin_index.html.erb +11 -0
- data/app/views/caboose/categories/admin_new.html.erb +62 -0
- data/app/views/caboose/checkout/_address_form.html.erb +111 -0
- data/app/views/caboose/checkout/_billing_form.html.erb +47 -0
- data/app/views/caboose/checkout/_cart.html.erb +52 -0
- data/app/views/caboose/checkout/_confirm.html.erb +61 -0
- data/app/views/caboose/checkout/_order_discount.html.erb +40 -0
- data/app/views/caboose/checkout/_shipping_address.html.erb +10 -0
- data/app/views/caboose/checkout/_shipping_method.html.erb +2 -0
- data/app/views/caboose/checkout/_shipping_method_form.html.erb +21 -0
- data/app/views/caboose/checkout/billing.html.erb +11 -0
- data/app/views/caboose/checkout/discount.html.erb +11 -0
- data/app/views/caboose/checkout/empty.html.erb +2 -0
- data/app/views/caboose/checkout/error.html.erb +2 -0
- data/app/views/caboose/checkout/index.html.erb +43 -0
- data/app/views/caboose/checkout/login.html.erb +2 -0
- data/app/views/caboose/checkout/payment.html.erb +79 -0
- data/app/views/caboose/checkout/relay.html.erb +23 -0
- data/app/views/caboose/checkout/relay_old.html.erb +12 -0
- data/app/views/caboose/checkout/relay_postMessage.html.erb +19 -0
- data/app/views/caboose/checkout/shipping.html.erb +15 -0
- data/app/views/caboose/checkout/step_four.html.erb +93 -0
- data/app/views/caboose/checkout/step_one.html.erb +56 -0
- data/app/views/caboose/checkout/step_one_old.html.erb +13 -0
- data/app/views/caboose/checkout/step_three.html.erb +23 -0
- data/app/views/caboose/checkout/step_two.html.erb +52 -0
- data/app/views/caboose/checkout/step_two_old.html.erb +14 -0
- data/app/views/caboose/checkout/thanks.html.erb +5 -0
- data/app/views/caboose/orders/_admin_footer.html.erb +2 -0
- data/app/views/caboose/orders/_admin_header.html.erb +31 -0
- data/app/views/caboose/orders/_quickbooks_order.html.erb +0 -0
- data/app/views/caboose/orders/admin_delete_form.html.erb +21 -0
- data/app/views/caboose/orders/admin_edit.html.erb +271 -0
- data/app/views/caboose/orders/admin_index.html.erb +89 -0
- data/app/views/caboose/orders/admin_new.html.erb +42 -0
- data/app/views/caboose/orders/admin_print.html.erb +72 -0
- data/app/views/caboose/orders_mailer/customer_new_order.html.erb +1 -0
- data/app/views/caboose/orders_mailer/customer_status_updated.html.erb +1 -0
- data/app/views/caboose/orders_mailer/fulfillment_new_order.html.erb +1 -0
- data/app/views/caboose/orders_mailer/shipping_order_ready.html.erb +1 -0
- data/app/views/caboose/products/_admin_footer.html.erb +2 -0
- data/app/views/caboose/products/_admin_header.html.erb +32 -0
- data/app/views/caboose/products/_sort_options.html.erb +19 -0
- data/app/views/caboose/products/admin_add_upcs.html.erb +58 -0
- data/app/views/caboose/products/admin_delete_form.html.erb +21 -0
- data/app/views/caboose/products/admin_edit_categories.html.erb +73 -0
- data/app/views/caboose/products/admin_edit_category_images.html.erb +233 -0
- data/app/views/caboose/products/admin_edit_description.html.erb +38 -0
- data/app/views/caboose/products/admin_edit_general.html.erb +104 -0
- data/app/views/caboose/products/admin_edit_images.html.erb +236 -0
- data/app/views/caboose/products/admin_edit_options.html.erb +51 -0
- data/app/views/caboose/products/admin_edit_seo.html.erb +37 -0
- data/app/views/caboose/products/admin_edit_variant_columns.html.erb +75 -0
- data/app/views/caboose/products/admin_edit_variant_sort_order.html.erb +63 -0
- data/app/views/caboose/products/admin_edit_variants.html.erb +171 -0
- data/app/views/caboose/products/admin_edit_variants_single.html.erb +68 -0
- data/app/views/caboose/products/admin_group_variants.html.erb +433 -0
- data/app/views/caboose/products/admin_index.html.erb +95 -0
- data/app/views/caboose/products/admin_new.html.erb +41 -0
- data/app/views/caboose/products/admin_sort.html copy.erb +155 -0
- data/app/views/caboose/products/admin_sort.html.erb +254 -0
- data/app/views/caboose/products/details.html.erb +438 -0
- data/app/views/caboose/products/index.html.erb +46 -0
- data/app/views/caboose/products/not_available.html.erb +35 -0
- data/app/views/caboose/variants/admin_edit.html.erb +82 -0
- data/app/views/caboose/variants/admin_group.html.erb +184 -0
- data/app/views/caboose/variants/admin_new.html.erb +59 -0
- data/app/views/caboose/vendors/admin_edit.html.erb +24 -0
- data/app/views/caboose/vendors/admin_index.html.erb +30 -0
- data/app/views/caboose/vendors/admin_new.html.erb +34 -0
- data/app/views/layouts/caboose/store/_banner.html.erb +10 -0
- data/app/views/layouts/caboose/store/_banner2.html.erb +10 -0
- data/app/views/layouts/caboose/store/_footer.html.erb +55 -0
- data/app/views/layouts/caboose/store/_header.html.erb +69 -0
- data/app/views/layouts/caboose/store/_sidebar.html.erb +27 -0
- data/app/views/layouts/caboose/store/application.html.erb +33 -0
- data/app/views/layouts/caboose/store/authorize_net.erb +18 -0
- data/app/views/layouts/caboose/store/layout_about.html.erb +42 -0
- data/app/views/layouts/caboose/store/layout_blog.html.erb +159 -0
- data/app/views/layouts/caboose/store/layout_confirm.html.erb +85 -0
- data/app/views/layouts/caboose/store/layout_contact.html.erb +38 -0
- data/app/views/layouts/caboose/store/layout_default.html.erb +10 -0
- data/app/views/layouts/caboose/store/layout_detail.html.erb +114 -0
- data/app/views/layouts/caboose/store/layout_order.html.erb +77 -0
- data/app/views/layouts/caboose/store/layout_pricing.html.erb +182 -0
- data/app/views/layouts/caboose/store/layout_product.html.erb +110 -0
- data/app/views/layouts/caboose/store/layout_profile.html.erb +55 -0
- data/app/views/layouts/caboose/store/layout_single.html.erb +3 -0
- data/app/views/layouts/caboose/store/layout_testimonial.html.erb +110 -0
- data/app/views/layouts/caboose/store/layout_testing.html.erb +4 -0
- data/config/routes.rb +126 -0
- data/lib/caboose.rb +46 -1
- data/lib/caboose/engine.rb +39 -1
- data/lib/caboose/version.rb +1 -1
- data/lib/tasks/caboose.rake +12 -0
- metadata +151 -4
- data/app/assets/javascripts/caboose/admin_page_edit_content_bak.js +0 -164
- 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
|
+
|