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.
Files changed (59) hide show
  1. data/app/assets/javascripts/shoppe/application.coffee +57 -1
  2. data/app/assets/javascripts/shoppe/mousetrap.js +9 -0
  3. data/app/assets/stylesheets/shoppe/application.scss +70 -59
  4. data/app/assets/stylesheets/shoppe/dialog.scss +10 -0
  5. data/app/assets/stylesheets/shoppe/sub.scss +15 -0
  6. data/app/controllers/shoppe/application_controller.rb +13 -1
  7. data/app/controllers/shoppe/attachments_controller.rb +10 -8
  8. data/app/controllers/shoppe/dashboard_controller.rb +6 -4
  9. data/app/controllers/shoppe/delivery_service_prices_controller.rb +33 -31
  10. data/app/controllers/shoppe/delivery_services_controller.rb +34 -32
  11. data/app/controllers/shoppe/orders_controller.rb +40 -38
  12. data/app/controllers/shoppe/product_categories_controller.rb +34 -32
  13. data/app/controllers/shoppe/products_controller.rb +32 -44
  14. data/app/controllers/shoppe/sessions_controller.rb +24 -22
  15. data/app/controllers/shoppe/stock_level_adjustments_controller.rb +40 -0
  16. data/app/controllers/shoppe/tax_rates_controller.rb +35 -33
  17. data/app/controllers/shoppe/users_controller.rb +40 -33
  18. data/app/controllers/shoppe/variants_controller.rb +50 -0
  19. data/app/helpers/shoppe/shoppe_helper.rb +2 -2
  20. data/app/mailers/shoppe/order_mailer.rb +20 -18
  21. data/app/models/shoppe/country.rb +1 -1
  22. data/app/models/shoppe/delivery_service.rb +17 -15
  23. data/app/models/shoppe/delivery_service_price.rb +18 -16
  24. data/app/models/shoppe/order.rb +293 -290
  25. data/app/models/shoppe/order_item.rb +115 -113
  26. data/app/models/shoppe/product.rb +76 -54
  27. data/app/models/shoppe/product/product_attributes.rb +12 -10
  28. data/app/models/shoppe/product/variants.rb +26 -0
  29. data/app/models/shoppe/product_attribute.rb +40 -38
  30. data/app/models/shoppe/product_category.rb +16 -14
  31. data/app/models/shoppe/stock_level_adjustment.rb +1 -2
  32. data/app/models/shoppe/tax_rate.rb +2 -2
  33. data/app/models/shoppe/user.rb +34 -32
  34. data/app/views/shoppe/orders/index.html.haml +3 -4
  35. data/app/views/shoppe/orders/show.html.haml +5 -5
  36. data/app/views/shoppe/products/_form.html.haml +28 -27
  37. data/app/views/shoppe/products/_table.html.haml +42 -0
  38. data/app/views/shoppe/products/edit.html.haml +2 -1
  39. data/app/views/shoppe/products/index.html.haml +1 -24
  40. data/app/views/shoppe/shared/error.html.haml +4 -0
  41. data/app/views/shoppe/{products/stock_levels.html.haml → stock_level_adjustments/index.html.haml} +12 -6
  42. data/app/views/shoppe/variants/form.html.haml +64 -0
  43. data/app/views/shoppe/variants/index.html.haml +33 -0
  44. data/config/routes.rb +2 -1
  45. data/config/shoppe.example.yml +16 -2
  46. data/db/migrate/20131022090919_refactor_order_items_to_allow_any_product.rb +6 -0
  47. data/db/migrate/20131022092904_rename_product_title_to_name.rb +5 -0
  48. data/db/migrate/20131022093538_stock_level_adjustments_should_be_polymorphic.rb +6 -0
  49. data/db/migrate/20131022135331_add_parent_id_to_products.rb +5 -0
  50. data/db/migrate/20131022145653_cost_price_should_be_default_to_zero.rb +9 -0
  51. data/db/seeds.rb +20 -20
  52. data/lib/shoppe.rb +2 -0
  53. data/lib/shoppe/errors/not_enough_stock.rb +1 -1
  54. data/lib/shoppe/errors/unorderable_item.rb +11 -0
  55. data/lib/shoppe/orderable_item.rb +39 -0
  56. data/lib/shoppe/version.rb +1 -1
  57. data/test/dummy/db/schema.rb +14 -11
  58. data/test/dummy/log/development.log +75 -0
  59. metadata +37 -5
@@ -1,41 +1,43 @@
1
- class Shoppe::OrdersController < Shoppe::ApplicationController
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
- class Shoppe::ProductCategoriesController < Shoppe::ApplicationController
1
+ module Shoppe
2
+ class ProductCategoriesController < Shoppe::ApplicationController
2
3
 
3
- before_filter { @active_nav = :product_categories }
4
- before_filter { params[:id] && @product_category = Shoppe::ProductCategory.find(params[:id]) }
4
+ before_filter { @active_nav = :product_categories }
5
+ before_filter { params[:id] && @product_category = Shoppe::ProductCategory.find(params[:id]) }
5
6
 
6
- def index
7
- @product_categories = Shoppe::ProductCategory.ordered.all
8
- end
7
+ def index
8
+ @product_categories = Shoppe::ProductCategory.ordered.all
9
+ end
9
10
 
10
- def new
11
- @product_category = Shoppe::ProductCategory.new
12
- end
11
+ def new
12
+ @product_category = Shoppe::ProductCategory.new
13
+ end
13
14
 
14
- def create
15
- @product_category = Shoppe::ProductCategory.new(safe_params)
16
- if @product_category.save
17
- redirect_to :product_categories, :flash => {:notice => "Category has been created successfully"}
18
- else
19
- render :action => "new"
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
- def edit
24
- end
24
+ def edit
25
+ end
25
26
 
26
- def update
27
- if @product_category.update(safe_params)
28
- redirect_to [:edit, @product_category], :flash => {:notice => "Category has been updated successfully"}
29
- else
30
- render :action => "edit"
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
- def destroy
35
- @product_category.destroy
36
- redirect_to :product_categories, :flash => {:notice => "Category has been removed successfully"}
37
- end
35
+ def destroy
36
+ @product_category.destroy
37
+ redirect_to :product_categories, :flash => {:notice => "Category has been removed successfully"}
38
+ end
38
39
 
39
- private
40
+ private
40
41
 
41
- def safe_params
42
- params[:product_category].permit(:name, :permalink, :description, :image_file)
43
- end
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
- class Shoppe::ProductsController < Shoppe::ApplicationController
1
+ module Shoppe
2
+ class ProductsController < Shoppe::ApplicationController
2
3
 
3
- before_filter { @active_nav = :products }
4
- before_filter { params[:id] && @product = Shoppe::Product.find(params[:id]) }
4
+ before_filter { @active_nav = :products }
5
+ before_filter { params[:id] && @product = Shoppe::Product.root.find(params[:id]) }
5
6
 
6
- def index
7
- @products = Shoppe::Product.includes(:stock_level_adjustments, :default_image, :product_category).order(:title).group_by(&:product_category).sort_by { |cat,pro| cat.name }
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
- def edit
24
- end
11
+ def new
12
+ @product = Shoppe::Product.new
13
+ end
25
14
 
26
- def update
27
- if @product.update(safe_params)
28
- redirect_to [:edit, @product], :flash => {:notice => "Product has been updated successfully"}
29
- else
30
- render :action => "edit"
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
- def destroy
35
- @product.destroy
36
- redirect_to :products, :flash => {:notice => "Product has been removed successfully"}
37
- end
24
+ def edit
25
+ end
38
26
 
39
- def stock_levels
40
- @stock_level_adjustments = @product.stock_level_adjustments.ordered.page(params[:page])
41
- if request.post?
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
- flash.now[:alert] = @new_sla.errors.full_messages.to_sentence
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
- private
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
- def safe_params
56
- params[:product].permit(:product_category_id, :title, :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])
57
- end
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
- class Shoppe::SessionsController < Shoppe::ApplicationController
2
- layout 'shoppe/sub'
3
- skip_before_filter :login_required, :only => [:new, :create, :reset]
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
- def create
6
- if user = Shoppe::User.authenticate(params[:email_address], params[:password])
7
- session[:shoppe_user_id] = user.id
8
- redirect_to :orders
9
- else
10
- flash.now[:alert] = "The email address and/or password you have entered is invalid. Please check and try again."
11
- render :action => "new"
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
- def destroy
16
- session[:shoppe_user_id] = nil
17
- redirect_to :login
18
- end
16
+ def destroy
17
+ session[:shoppe_user_id] = nil
18
+ redirect_to :login
19
+ end
19
20
 
20
- def reset
21
+ def reset
21
22
 
22
- if request.post?
23
- if user = Shoppe::User.find_by_email_address(params[:email_address])
24
- user.reset_password!
25
- redirect_to login_path(:email_address => params[:email_address]), :notice => "An e-mail has been sent to #{user.email_address} with a new password"
26
- else
27
- flash.now[:alert] = "No user was found matching the e-mail address"
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
- class Shoppe::TaxRatesController < Shoppe::ApplicationController
1
+ module Shoppe
2
+ class TaxRatesController < Shoppe::ApplicationController
2
3
 
3
- before_filter { @active_nav = :tax_rates }
4
- before_filter { params[:id] && @tax_rate = Shoppe::TaxRate.find(params[:id]) }
4
+ before_filter { @active_nav = :tax_rates }
5
+ before_filter { params[:id] && @tax_rate = Shoppe::TaxRate.find(params[:id]) }
5
6
 
6
- def index
7
- @tax_rates = Shoppe::TaxRate.ordered.all
8
- end
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
- def create
16
- @tax_rate = Shoppe::TaxRate.new(safe_params)
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
- def edit
25
- render :action => "form"
26
- end
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
- def update
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
- def destroy
37
- @tax_rate.destroy
38
- redirect_to :tax_rates, :flash => {:notice => "Tax rate has been removed successfully"}
39
- end
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
- private
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
- def safe_params
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
- class Shoppe::UsersController < Shoppe::ApplicationController
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
- before_filter { @active_nav = :users }
4
- before_filter { params[:id] && @user = Shoppe::User.find(params[:id]) }
12
+ def index
13
+ @users = Shoppe::User.all
14
+ end
5
15
 
6
- def index
7
- @users = Shoppe::User.all
8
- end
16
+ def new
17
+ @user = Shoppe::User.new
18
+ end
9
19
 
10
- def new
11
- @user = Shoppe::User.new
12
- end
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
- def create
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
- def edit
24
- end
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
- def update
27
- if @user.update(safe_params)
28
- redirect_to [:edit, @user], :flash => {:notice => "User has been updated successfully"}
29
- else
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
- def destroy
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
- private
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