shoppe 0.0.14 → 0.0.15
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.
- data/app/assets/javascripts/shoppe/application.coffee +57 -1
- data/app/assets/javascripts/shoppe/mousetrap.js +9 -0
- data/app/assets/stylesheets/shoppe/application.scss +70 -59
- data/app/assets/stylesheets/shoppe/dialog.scss +10 -0
- data/app/assets/stylesheets/shoppe/sub.scss +15 -0
- data/app/controllers/shoppe/application_controller.rb +13 -1
- data/app/controllers/shoppe/attachments_controller.rb +10 -8
- data/app/controllers/shoppe/dashboard_controller.rb +6 -4
- data/app/controllers/shoppe/delivery_service_prices_controller.rb +33 -31
- data/app/controllers/shoppe/delivery_services_controller.rb +34 -32
- data/app/controllers/shoppe/orders_controller.rb +40 -38
- data/app/controllers/shoppe/product_categories_controller.rb +34 -32
- data/app/controllers/shoppe/products_controller.rb +32 -44
- data/app/controllers/shoppe/sessions_controller.rb +24 -22
- data/app/controllers/shoppe/stock_level_adjustments_controller.rb +40 -0
- data/app/controllers/shoppe/tax_rates_controller.rb +35 -33
- data/app/controllers/shoppe/users_controller.rb +40 -33
- data/app/controllers/shoppe/variants_controller.rb +50 -0
- data/app/helpers/shoppe/shoppe_helper.rb +2 -2
- data/app/mailers/shoppe/order_mailer.rb +20 -18
- data/app/models/shoppe/country.rb +1 -1
- data/app/models/shoppe/delivery_service.rb +17 -15
- data/app/models/shoppe/delivery_service_price.rb +18 -16
- data/app/models/shoppe/order.rb +293 -290
- data/app/models/shoppe/order_item.rb +115 -113
- data/app/models/shoppe/product.rb +76 -54
- data/app/models/shoppe/product/product_attributes.rb +12 -10
- data/app/models/shoppe/product/variants.rb +26 -0
- data/app/models/shoppe/product_attribute.rb +40 -38
- data/app/models/shoppe/product_category.rb +16 -14
- data/app/models/shoppe/stock_level_adjustment.rb +1 -2
- data/app/models/shoppe/tax_rate.rb +2 -2
- data/app/models/shoppe/user.rb +34 -32
- data/app/views/shoppe/orders/index.html.haml +3 -4
- data/app/views/shoppe/orders/show.html.haml +5 -5
- data/app/views/shoppe/products/_form.html.haml +28 -27
- data/app/views/shoppe/products/_table.html.haml +42 -0
- data/app/views/shoppe/products/edit.html.haml +2 -1
- data/app/views/shoppe/products/index.html.haml +1 -24
- data/app/views/shoppe/shared/error.html.haml +4 -0
- data/app/views/shoppe/{products/stock_levels.html.haml → stock_level_adjustments/index.html.haml} +12 -6
- data/app/views/shoppe/variants/form.html.haml +64 -0
- data/app/views/shoppe/variants/index.html.haml +33 -0
- data/config/routes.rb +2 -1
- data/config/shoppe.example.yml +16 -2
- data/db/migrate/20131022090919_refactor_order_items_to_allow_any_product.rb +6 -0
- data/db/migrate/20131022092904_rename_product_title_to_name.rb +5 -0
- data/db/migrate/20131022093538_stock_level_adjustments_should_be_polymorphic.rb +6 -0
- data/db/migrate/20131022135331_add_parent_id_to_products.rb +5 -0
- data/db/migrate/20131022145653_cost_price_should_be_default_to_zero.rb +9 -0
- data/db/seeds.rb +20 -20
- data/lib/shoppe.rb +2 -0
- data/lib/shoppe/errors/not_enough_stock.rb +1 -1
- data/lib/shoppe/errors/unorderable_item.rb +11 -0
- data/lib/shoppe/orderable_item.rb +39 -0
- data/lib/shoppe/version.rb +1 -1
- data/test/dummy/db/schema.rb +14 -11
- data/test/dummy/log/development.log +75 -0
- metadata +37 -5
@@ -1,41 +1,43 @@
|
|
1
|
-
|
1
|
+
module Shoppe
|
2
|
+
class OrdersController < Shoppe::ApplicationController
|
3
|
+
|
4
|
+
before_filter { @active_nav = :orders }
|
5
|
+
before_filter { params[:id] && @order = Shoppe::Order.find(params[:id])}
|
6
|
+
|
7
|
+
def index
|
8
|
+
@query = Shoppe::Order.ordered.received.includes(:order_items => :ordered_item).page(params[:page]).search(params[:q])
|
9
|
+
@orders = @query.result
|
10
|
+
end
|
11
|
+
|
12
|
+
def update
|
13
|
+
@order.update_attributes!(params[:order].permit(:notes))
|
14
|
+
redirect_to @order, :notice => "Order has been saved successfully"
|
15
|
+
end
|
16
|
+
|
17
|
+
def search
|
18
|
+
index
|
19
|
+
render :action => "index"
|
20
|
+
end
|
21
|
+
|
22
|
+
def accept
|
23
|
+
@order.accept!(current_user)
|
24
|
+
redirect_to @order, :notice => "Order has been accepted successfully"
|
25
|
+
end
|
26
|
+
|
27
|
+
def reject
|
28
|
+
@order.reject!(current_user)
|
29
|
+
redirect_to @order, :notice => "Order has been rejected successfully"
|
30
|
+
end
|
31
|
+
|
32
|
+
def ship
|
33
|
+
@order.ship!(current_user, params[:consignment_number])
|
34
|
+
redirect_to @order, :notice => "Order has been shipped successfully"
|
35
|
+
end
|
36
|
+
|
37
|
+
def pay
|
38
|
+
@order.pay!(params[:payment_reference], params[:payment_method].blank? ? 'Unknown' : params[:payment_method])
|
39
|
+
redirect_to @order, :notice => "Order has been marked as paid successfully"
|
40
|
+
end
|
2
41
|
|
3
|
-
before_filter { @active_nav = :orders }
|
4
|
-
before_filter { params[:id] && @order = Shoppe::Order.find(params[:id])}
|
5
|
-
|
6
|
-
def index
|
7
|
-
@query = Shoppe::Order.ordered.received.includes(:order_items => :product).page(params[:page]).search(params[:q])
|
8
|
-
@orders = @query.result
|
9
|
-
end
|
10
|
-
|
11
|
-
def update
|
12
|
-
@order.update_attributes!(params[:order].permit(:notes))
|
13
|
-
redirect_to @order, :notice => "Order has been saved successfully"
|
14
|
-
end
|
15
|
-
|
16
|
-
def search
|
17
|
-
index
|
18
|
-
render :action => "index"
|
19
|
-
end
|
20
|
-
|
21
|
-
def accept
|
22
|
-
@order.accept!(current_user)
|
23
|
-
redirect_to @order, :notice => "Order has been accepted successfully"
|
24
42
|
end
|
25
|
-
|
26
|
-
def reject
|
27
|
-
@order.reject!(current_user)
|
28
|
-
redirect_to @order, :notice => "Order has been rejected successfully"
|
29
|
-
end
|
30
|
-
|
31
|
-
def ship
|
32
|
-
@order.ship!(current_user, params[:consignment_number])
|
33
|
-
redirect_to @order, :notice => "Order has been shipped successfully"
|
34
|
-
end
|
35
|
-
|
36
|
-
def pay
|
37
|
-
@order.pay!(params[:payment_reference], params[:payment_method].blank? ? 'Unknown' : params[:payment_method])
|
38
|
-
redirect_to @order, :notice => "Order has been marked as paid successfully"
|
39
|
-
end
|
40
|
-
|
41
43
|
end
|
@@ -1,45 +1,47 @@
|
|
1
|
-
|
1
|
+
module Shoppe
|
2
|
+
class ProductCategoriesController < Shoppe::ApplicationController
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
before_filter { @active_nav = :product_categories }
|
5
|
+
before_filter { params[:id] && @product_category = Shoppe::ProductCategory.find(params[:id]) }
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def index
|
8
|
+
@product_categories = Shoppe::ProductCategory.ordered.all
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
def new
|
12
|
+
@product_category = Shoppe::ProductCategory.new
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
def create
|
16
|
+
@product_category = Shoppe::ProductCategory.new(safe_params)
|
17
|
+
if @product_category.save
|
18
|
+
redirect_to :product_categories, :flash => {:notice => "Category has been created successfully"}
|
19
|
+
else
|
20
|
+
render :action => "new"
|
21
|
+
end
|
20
22
|
end
|
21
|
-
end
|
22
23
|
|
23
|
-
|
24
|
-
|
24
|
+
def edit
|
25
|
+
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
def update
|
28
|
+
if @product_category.update(safe_params)
|
29
|
+
redirect_to [:edit, @product_category], :flash => {:notice => "Category has been updated successfully"}
|
30
|
+
else
|
31
|
+
render :action => "edit"
|
32
|
+
end
|
31
33
|
end
|
32
|
-
end
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
def destroy
|
36
|
+
@product_category.destroy
|
37
|
+
redirect_to :product_categories, :flash => {:notice => "Category has been removed successfully"}
|
38
|
+
end
|
38
39
|
|
39
|
-
|
40
|
+
private
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
def safe_params
|
43
|
+
params[:product_category].permit(:name, :permalink, :description, :image_file)
|
44
|
+
end
|
44
45
|
|
46
|
+
end
|
45
47
|
end
|
@@ -1,59 +1,47 @@
|
|
1
|
-
|
1
|
+
module Shoppe
|
2
|
+
class ProductsController < Shoppe::ApplicationController
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
before_filter { @active_nav = :products }
|
5
|
+
before_filter { params[:id] && @product = Shoppe::Product.root.find(params[:id]) }
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
end
|
9
|
-
|
10
|
-
def new
|
11
|
-
@product = Shoppe::Product.new
|
12
|
-
end
|
13
|
-
|
14
|
-
def create
|
15
|
-
@product = Shoppe::Product.new(safe_params)
|
16
|
-
if @product.save
|
17
|
-
redirect_to :products, :flash => {:notice => "Product has been created successfully"}
|
18
|
-
else
|
19
|
-
render :action => "new"
|
7
|
+
def index
|
8
|
+
@products = Shoppe::Product.root.includes(:stock_level_adjustments, :default_image, :product_category, :variants).order(:name).group_by(&:product_category).sort_by { |cat,pro| cat.name }
|
20
9
|
end
|
21
|
-
end
|
22
10
|
|
23
|
-
|
24
|
-
|
11
|
+
def new
|
12
|
+
@product = Shoppe::Product.new
|
13
|
+
end
|
25
14
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
15
|
+
def create
|
16
|
+
@product = Shoppe::Product.new(safe_params)
|
17
|
+
if @product.save
|
18
|
+
redirect_to :products, :flash => {:notice => "Product has been created successfully"}
|
19
|
+
else
|
20
|
+
render :action => "new"
|
21
|
+
end
|
31
22
|
end
|
32
|
-
end
|
33
23
|
|
34
|
-
|
35
|
-
|
36
|
-
redirect_to :products, :flash => {:notice => "Product has been removed successfully"}
|
37
|
-
end
|
24
|
+
def edit
|
25
|
+
end
|
38
26
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
@new_sla = @product.stock_level_adjustments.build(params[:stock_level_adjustment].permit(:description, :adjustment))
|
43
|
-
if @new_sla.save
|
44
|
-
redirect_to [:stock_levels, @product], :notice => "Stock level adjustment has been recorded"
|
27
|
+
def update
|
28
|
+
if @product.update(safe_params)
|
29
|
+
redirect_to [:edit, @product], :flash => {:notice => "Product has been updated successfully"}
|
45
30
|
else
|
46
|
-
|
31
|
+
render :action => "edit"
|
47
32
|
end
|
48
|
-
else
|
49
|
-
@new_sla = @product.stock_level_adjustments.build
|
50
33
|
end
|
51
|
-
end
|
52
34
|
|
53
|
-
|
35
|
+
def destroy
|
36
|
+
@product.destroy
|
37
|
+
redirect_to :products, :flash => {:notice => "Product has been removed successfully"}
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
54
41
|
|
55
|
-
|
56
|
-
|
57
|
-
|
42
|
+
def safe_params
|
43
|
+
params[:product].permit(:product_category_id, :name, :sku, :permalink, :description, :short_description, :weight, :price, :cost_price, :tax_rate_id, :stock_control, :default_image_file, :data_sheet_file, :active, :featured, :in_the_box, :product_attributes_array => [:key, :value, :searchable, :public])
|
44
|
+
end
|
58
45
|
|
46
|
+
end
|
59
47
|
end
|
@@ -1,30 +1,32 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module Shoppe
|
2
|
+
class SessionsController < Shoppe::ApplicationController
|
3
|
+
layout 'shoppe/sub'
|
4
|
+
skip_before_filter :login_required, :only => [:new, :create, :reset]
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
def create
|
7
|
+
if user = Shoppe::User.authenticate(params[:email_address], params[:password])
|
8
|
+
session[:shoppe_user_id] = user.id
|
9
|
+
redirect_to :orders
|
10
|
+
else
|
11
|
+
flash.now[:alert] = "The email address and/or password you have entered is invalid. Please check and try again."
|
12
|
+
render :action => "new"
|
13
|
+
end
|
12
14
|
end
|
13
|
-
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
def destroy
|
17
|
+
session[:shoppe_user_id] = nil
|
18
|
+
redirect_to :login
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
+
def reset
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
if request.post?
|
24
|
+
if user = Shoppe::User.find_by_email_address(params[:email_address])
|
25
|
+
user.reset_password!
|
26
|
+
redirect_to login_path(:email_address => params[:email_address]), :notice => "An e-mail has been sent to #{user.email_address} with a new password"
|
27
|
+
else
|
28
|
+
flash.now[:alert] = "No user was found matching the e-mail address"
|
29
|
+
end
|
28
30
|
end
|
29
31
|
end
|
30
32
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Shoppe
|
2
|
+
class StockLevelAdjustmentsController < ApplicationController
|
3
|
+
|
4
|
+
SUITABLE_OBJECTS = ['Shoppe::Product']
|
5
|
+
before_filter do
|
6
|
+
raise Shoppe::Error, "Invalid item_type (must be one of #{SUITABLE_OBJECTS.to_sentence})" unless SUITABLE_OBJECTS.include?(params[:item_type])
|
7
|
+
@item = params[:item_type].constantize.find(params[:item_id].to_i)
|
8
|
+
end
|
9
|
+
before_filter { params[:id] && @sla = @item.stock_level_adjustments.find(params[:id].to_i) }
|
10
|
+
|
11
|
+
def index
|
12
|
+
@stock_level_adjustments = @item.stock_level_adjustments.ordered.page(params[:page]).per(10)
|
13
|
+
@new_sla = @item.stock_level_adjustments.build if @new_sla.nil?
|
14
|
+
if request.xhr?
|
15
|
+
render :action => 'index', :layout => false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def create
|
20
|
+
@new_sla = @item.stock_level_adjustments.build(params[:stock_level_adjustment].permit(:description, :adjustment))
|
21
|
+
if @new_sla.save
|
22
|
+
if request.xhr?
|
23
|
+
@new_sla = @item.stock_level_adjustments.build
|
24
|
+
index
|
25
|
+
else
|
26
|
+
redirect_to stock_level_adjustments_path(:item_id => params[:item_id], :item_type => params[:item_type]), :notice => "Adjustment has been added successfully"
|
27
|
+
end
|
28
|
+
else
|
29
|
+
if request.xhr?
|
30
|
+
render :text => @new_sla.errors.full_messages.to_sentence, :status => 422
|
31
|
+
else
|
32
|
+
index
|
33
|
+
flash.now[:alert] = @new_sla.errors.full_messages.to_sentence
|
34
|
+
render :action => "index"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -1,47 +1,49 @@
|
|
1
|
-
|
1
|
+
module Shoppe
|
2
|
+
class TaxRatesController < Shoppe::ApplicationController
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
before_filter { @active_nav = :tax_rates }
|
5
|
+
before_filter { params[:id] && @tax_rate = Shoppe::TaxRate.find(params[:id]) }
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def new
|
11
|
-
@tax_rate = Shoppe::TaxRate.new
|
12
|
-
render :action => "form"
|
13
|
-
end
|
7
|
+
def index
|
8
|
+
@tax_rates = Shoppe::TaxRate.ordered.all
|
9
|
+
end
|
14
10
|
|
15
|
-
|
16
|
-
|
17
|
-
if @tax_rate.save
|
18
|
-
redirect_to :tax_rates, :flash => {:notice => "Tax rate has been created successfully"}
|
19
|
-
else
|
11
|
+
def new
|
12
|
+
@tax_rate = Shoppe::TaxRate.new
|
20
13
|
render :action => "form"
|
21
14
|
end
|
22
|
-
end
|
23
15
|
|
24
|
-
|
25
|
-
|
26
|
-
|
16
|
+
def create
|
17
|
+
@tax_rate = Shoppe::TaxRate.new(safe_params)
|
18
|
+
if @tax_rate.save
|
19
|
+
redirect_to :tax_rates, :flash => {:notice => "Tax rate has been created successfully"}
|
20
|
+
else
|
21
|
+
render :action => "form"
|
22
|
+
end
|
23
|
+
end
|
27
24
|
|
28
|
-
|
29
|
-
if @tax_rate.update(safe_params)
|
30
|
-
redirect_to [:edit, @tax_rate], :flash => {:notice => "Tax rate has been updated successfully"}
|
31
|
-
else
|
25
|
+
def edit
|
32
26
|
render :action => "form"
|
33
27
|
end
|
34
|
-
end
|
35
28
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
29
|
+
def update
|
30
|
+
if @tax_rate.update(safe_params)
|
31
|
+
redirect_to [:edit, @tax_rate], :flash => {:notice => "Tax rate has been updated successfully"}
|
32
|
+
else
|
33
|
+
render :action => "form"
|
34
|
+
end
|
35
|
+
end
|
40
36
|
|
41
|
-
|
37
|
+
def destroy
|
38
|
+
@tax_rate.destroy
|
39
|
+
redirect_to :tax_rates, :flash => {:notice => "Tax rate has been removed successfully"}
|
40
|
+
end
|
42
41
|
|
43
|
-
|
44
|
-
params[:tax_rate].permit(:name, :rate, :country_ids => [])
|
45
|
-
end
|
42
|
+
private
|
46
43
|
|
44
|
+
def safe_params
|
45
|
+
params[:tax_rate].permit(:name, :rate, :country_ids => [])
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
47
49
|
end
|
@@ -1,46 +1,53 @@
|
|
1
|
-
|
1
|
+
module Shoppe
|
2
|
+
class UsersController < Shoppe::ApplicationController
|
3
|
+
|
4
|
+
before_filter { @active_nav = :users }
|
5
|
+
before_filter { params[:id] && @user = Shoppe::User.find(params[:id]) }
|
6
|
+
if Shoppe.config[:demo_mode]
|
7
|
+
before_filter(:only => [:create, :update, :destroy]) do
|
8
|
+
raise Shoppe::Error, "You cannot make changes to user in demo mode. Sorry about that."
|
9
|
+
end
|
10
|
+
end
|
2
11
|
|
3
|
-
|
4
|
-
|
12
|
+
def index
|
13
|
+
@users = Shoppe::User.all
|
14
|
+
end
|
5
15
|
|
6
|
-
|
7
|
-
|
8
|
-
|
16
|
+
def new
|
17
|
+
@user = Shoppe::User.new
|
18
|
+
end
|
9
19
|
|
10
|
-
|
11
|
-
|
12
|
-
|
20
|
+
def create
|
21
|
+
@user = Shoppe::User.new(safe_params)
|
22
|
+
if @user.save
|
23
|
+
redirect_to :users, :flash => {:notice => "User has been created successfully"}
|
24
|
+
else
|
25
|
+
render :action => "new"
|
26
|
+
end
|
27
|
+
end
|
13
28
|
|
14
|
-
|
15
|
-
@user = Shoppe::User.new(safe_params)
|
16
|
-
if @user.save
|
17
|
-
redirect_to :users, :flash => {:notice => "User has been created successfully"}
|
18
|
-
else
|
19
|
-
render :action => "new"
|
29
|
+
def edit
|
20
30
|
end
|
21
|
-
end
|
22
31
|
|
23
|
-
|
24
|
-
|
32
|
+
def update
|
33
|
+
if @user.update(safe_params)
|
34
|
+
redirect_to [:edit, @user], :flash => {:notice => "User has been updated successfully"}
|
35
|
+
else
|
36
|
+
render :action => "edit"
|
37
|
+
end
|
38
|
+
end
|
25
39
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
render :action => "edit"
|
40
|
+
def destroy
|
41
|
+
raise Shoppe::Error, "You cannot remove yourself" if @user == current_user
|
42
|
+
@user.destroy
|
43
|
+
redirect_to :users, :flash => {:notice => "User has been removed successfully"}
|
31
44
|
end
|
32
|
-
end
|
33
45
|
|
34
|
-
|
35
|
-
raise Shoppe::Error, "You cannot remove yourself" if @user == current_user
|
36
|
-
@user.destroy
|
37
|
-
redirect_to :users, :flash => {:notice => "User has been removed successfully"}
|
38
|
-
end
|
46
|
+
private
|
39
47
|
|
40
|
-
|
48
|
+
def safe_params
|
49
|
+
params[:user].permit(:first_name, :last_name, :email_address, :password, :password_confirmation)
|
50
|
+
end
|
41
51
|
|
42
|
-
def safe_params
|
43
|
-
params[:user].permit(:first_name, :last_name, :email_address, :password, :password_confirmation)
|
44
52
|
end
|
45
|
-
|
46
53
|
end
|