From 9e722746293fcfd814f90db97d763aadf258de88 Mon Sep 17 00:00:00 2001 From: benji Date: Thu, 15 Jan 2015 00:39:34 +0100 Subject: [PATCH] add stock to products and some clean up --- app/assets/javascripts/orders.js.coffee | 8 +++++-- app/controllers/application_controller.rb | 7 +++--- app/controllers/orders_controller.rb | 11 +++++----- app/controllers/products_controller.rb | 4 ++-- app/controllers/users_controller.rb | 4 ++-- app/helpers/application_helper.rb | 5 ----- app/helpers/orders_helper.rb | 7 ------ app/models/order.rb | 22 +++++++++---------- app/models/order_product.rb | 9 ++++++++ app/models/product.rb | 2 ++ app/models/user.rb | 7 +++--- app/validators/in_stock_validator.rb | 7 ++++++ app/views/devise/registrations/edit.html.erb | 1 + app/views/layouts/application.html.erb | 5 ----- app/views/order_products/_form_row.html.erb | 19 ---------------- .../order_products/_order_product.html.erb | 20 +++++++++++++++++ .../order_products/_total_price.html.erb | 16 ++++++++------ app/views/orders/_order.html.erb | 6 +---- app/views/orders/_overview.html.erb | 6 +++++ app/views/orders/_user_list.html.erb | 9 -------- app/views/orders/new.html.erb | 9 +++----- app/views/orders/overview.html.erb | 11 ++-------- app/views/products/_category.html.erb | 4 +--- app/views/products/_form.html.erb | 3 +++ app/views/products/_product.html.erb | 10 +++++---- app/views/products/_product_row.html.erb | 4 +--- app/views/users/_new_order.html.erb | 7 ++++++ app/views/users/_user.html.erb | 2 +- .../20150113155744_add_stock_to_products.rb | 5 +++++ db/schema.rb | 3 ++- test/fixtures/products.yml | 1 + test/fixtures/users.yml | 1 + test/models/product_test.rb | 1 + test/models/user_test.rb | 1 + 34 files changed, 123 insertions(+), 114 deletions(-) create mode 100644 app/validators/in_stock_validator.rb delete mode 100644 app/views/order_products/_form_row.html.erb create mode 100644 app/views/order_products/_order_product.html.erb create mode 100644 app/views/orders/_overview.html.erb delete mode 100644 app/views/orders/_user_list.html.erb create mode 100644 app/views/users/_new_order.html.erb create mode 100644 db/migrate/20150113155744_add_stock_to_products.rb diff --git a/app/assets/javascripts/orders.js.coffee b/app/assets/javascripts/orders.js.coffee index 9eab234..82460bb 100644 --- a/app/assets/javascripts/orders.js.coffee +++ b/app/assets/javascripts/orders.js.coffee @@ -9,14 +9,18 @@ ready = -> increment($(this), -1) $('.btn-dec').prop("disabled", true) + $('.btn-inc').each((index, button) -> + $(button).prop("disabled", $(button).closest('.form_row').find('.stock').val() == '0') + ) increment = (button, n) -> # Fix the counter counter = $(button).closest('.form_row').find('.row_counter') counter.val(parseInt(counter.val()) + n) - # Enable or disable the dec button - counter.parent().find('.btn-dec').prop("disabled", counter.val() == '0'); + # Enable or disable the buttons + counter.parent().find('.btn-dec').prop('disabled', counter.val() == '0'); + counter.parent().find('.btn-inc').prop('disabled', counter.val() == counter.parent().find('.stock').val()); # Update the price oldVal = parseFloat($('#order_total_price').val()) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 6dc5891..e1b823c 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -5,8 +5,7 @@ class ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? rescue_from CanCan::AccessDenied do |exception| - flash[:error] = exception.message - redirect_to root_path + redirect_to root_path, flash: { error: exception.message } end def after_sign_in_path_for(resource) @@ -14,7 +13,7 @@ class ApplicationController < ActionController::Base end def after_sign_up_path_for(resource) - new_user_session_path + root_path end protected @@ -24,9 +23,9 @@ class ApplicationController < ActionController::Base :nickname, :name, :last_name, :password, :password_confirmation, :current_password, :avatar ) } + devise_parameter_sanitizer.for(:account_update) { |u| u.permit( :password, :password_confirmation, :current_password, :avatar ) } end - end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 49a3d62..9f7f4ea 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -19,8 +19,9 @@ class OrdersController < ApplicationController @order = @user.orders.build(order_params) @products = Product.all @order_products = @order.order_products + if @order.save - flash[:success] = order_to_sentence(@order) + " ordered. Enjoy it!" + flash[:success] = "#{@order.to_sentence} ordered. Enjoy it!" redirect_to root_path else render 'new' @@ -33,13 +34,13 @@ class OrdersController < ApplicationController end def quickpay - @user = User.find(params[:user_id]) - order = @user.orders.build - order.products << @user.dagschotel + user = User.find(params[:user_id]) + order = user.orders.build + order.products << user.dagschotel if order.save flash[:success] = "Quick pay succeeded" else - flash[:error] = "Quick pay went wrong ... Sorry!" + flash[:error] = order.errors.full_messages.first end redirect_to root_path end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 1503814..8f7223c 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -36,13 +36,13 @@ class ProductsController < ApplicationController def destroy Product.find(params[:id]).destroy flash[:success] = "Succesfully removed product" - redirect_to products_path + redirect_to action: :index end private def product_params - params.require(:product).permit(:name, :price, :avatar, :category) + params.require(:product).permit(:name, :price, :avatar, :category, :stock) end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 65bde11..6dd3098 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,5 +1,5 @@ class UsersController < ApplicationController - load_and_authorize_resource only: [:destroy] + load_and_authorize_resource def show @user = User.find_by_id(params[:id]) || current_user @@ -15,7 +15,7 @@ class UsersController < ApplicationController def destroy User.find(params[:id]).destroy flash[:success] = "Succesfully removed user" - redirect_to users_path + redirect_to action: :index end def dagschotel diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 251c11f..30a084a 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -13,11 +13,6 @@ module ApplicationHelper "€#{number_with_precision f, precision: 2}" end - #tijdelijk voor layout - def koelkast(status) - @koelkast ||= status - end - # Form helpers def form_errors(object) render partial: "form_errors", locals: {object: object} diff --git a/app/helpers/orders_helper.rb b/app/helpers/orders_helper.rb index 96d4633..443227f 100644 --- a/app/helpers/orders_helper.rb +++ b/app/helpers/orders_helper.rb @@ -1,9 +1,2 @@ module OrdersHelper - include ActionView::Helpers::TextHelper - - def order_to_sentence(order) - order.order_products.map { - |op| pluralize(op.count, op.product.name) - }.to_sentence - end end diff --git a/app/models/order.rb b/app/models/order.rb index aed4b45..11d129f 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -10,8 +10,10 @@ # class Order < ActiveRecord::Base + include ActionView::Helpers::TextHelper + after_initialize { self.total_price = 0 } - after_create :pay_price + after_create { self.user.pay(price) } belongs_to :user, counter_cache: true has_many :order_products @@ -20,21 +22,17 @@ class Order < ActiveRecord::Base attr_accessor :total_price validates :user, presence: true - validates :order_products, presence: true + validates :order_products, presence: true, in_stock: true accepts_nested_attributes_for :order_products, reject_if: proc { |op| op[:count].to_i <= 0 } def price - price = 0 - order_products.each do |op| - price += op.count * op.product.read_attribute(:price) - end - price + self.order_products.map{ |op| op.count * op.product.price }.sum end - private - - def pay_price - user.pay(price) - end + def to_sentence + self.order_products.map { + |op| pluralize(op.count, op.product.name) + }.to_sentence + end end diff --git a/app/models/order_product.rb b/app/models/order_product.rb index 0ac8ac4..a50d958 100644 --- a/app/models/order_product.rb +++ b/app/models/order_product.rb @@ -9,6 +9,8 @@ # class OrderProduct < ActiveRecord::Base + after_create :remove_from_stock + belongs_to :order belongs_to :product @@ -16,4 +18,11 @@ class OrderProduct < ActiveRecord::Base validates :count, numericality: { greater_than_or_equal_to: 0 } accepts_nested_attributes_for :product + + private + + def remove_from_stock + product.stock -= self.count + product.save + end end diff --git a/app/models/product.rb b/app/models/product.rb index 131189a..9dd33d6 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -12,6 +12,7 @@ # avatar_file_size :integer # avatar_updated_at :datetime # category :integer default(0) +# stock :integer default(0) # class Product < ActiveRecord::Base @@ -22,6 +23,7 @@ class Product < ActiveRecord::Base validates :name, presence: true validates :price, numericality: { only_integer: true, greater_than_or_equal_to: 0 } + validates :stock, numericality: { only_integer: true, greater_than_or_equal_to: 0 } validates_attachment :avatar, presence: true, content_type: { content_type: ["image/jpeg", "image/gif", "image/png"] } def price diff --git a/app/models/user.rb b/app/models/user.rb index 729dd2f..5270616 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -23,12 +23,13 @@ # avatar_file_size :integer # avatar_updated_at :datetime # orders_count :integer default(0) +# koelkast :boolean default(FALSE) # class User < ActiveRecord::Base - devise :database_authenticatable, :registerable, - :rememberable, :trackable - has_attached_file :avatar, styles: { medium: "100x100>" }, default_style: :medium, default_url: "http://babeholder.pixoil.com/img/70/70" + devise :database_authenticatable, :registerable, :rememberable, :trackable + has_attached_file :avatar, styles: { medium: "100x100>" }, default_style: :medium, + default_url: "http://babeholder.pixoil.com/img/70/70" has_many :orders, -> { includes :products } has_many :products, through: :orders diff --git a/app/validators/in_stock_validator.rb b/app/validators/in_stock_validator.rb new file mode 100644 index 0000000..8705fc0 --- /dev/null +++ b/app/validators/in_stock_validator.rb @@ -0,0 +1,7 @@ +class InStockValidator < ActiveModel::Validator + def validate(record) + record.order_products.each do |op| + record.errors[op.product.name] = "is not in stock anymore" if op.count > op.product.stock + end + end +end diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 724991f..e73609c 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -1,4 +1,5 @@

Edit <%= resource_name.to_s.humanize %>

+<%= render 'flash' %> <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %> <%= devise_error_messages! %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 47a426c..641d265 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -15,11 +15,6 @@ <%= render "layouts/footer" %> <%= debug(params) if Rails.env.development? %> - - - - - diff --git a/app/views/order_products/_form_row.html.erb b/app/views/order_products/_form_row.html.erb deleted file mode 100644 index 33ddf71..0000000 --- a/app/views/order_products/_form_row.html.erb +++ /dev/null @@ -1,19 +0,0 @@ -
-
-
- <%= image_tag f.object.product.avatar %> -
-

<%= f.object.product.name %> - <%= content_tag :span, euro(f.object.product.price), class: "price" %>

-

-

- <%= render 'btn_dec', id: f.object.product_id %> - <%= f.text_field :count, class: 'form-control row_counter', value: 0 %> - <%= f.hidden_field :price, value: f.object.product.price, class: :price %> - <%= render 'btn_inc', id: f.object.product_id %> - <%= f.hidden_field :product_id %> -
-

-
-
-
-
diff --git a/app/views/order_products/_order_product.html.erb b/app/views/order_products/_order_product.html.erb new file mode 100644 index 0000000..f826424 --- /dev/null +++ b/app/views/order_products/_order_product.html.erb @@ -0,0 +1,20 @@ +
+
+
+ <%= image_tag product.avatar %> +
+

<%= product.name %> - <%= content_tag :span, euro(product.price), class: "price" %>

+

+

+ <%= render 'btn_dec', id: product.id %> + <%= f.text_field :count, class: 'form-control row_counter', value: 0 %> + <%= f.hidden_field :price, value: product.price, class: :price %> + <%= f.hidden_field :stock, value: product.stock, class: :stock %> + <%= render 'btn_inc', id: product.id %> + <%= f.hidden_field :product_id %> +
+

+
+
+
+
diff --git a/app/views/order_products/_total_price.html.erb b/app/views/order_products/_total_price.html.erb index 7355580..658f889 100644 --- a/app/views/order_products/_total_price.html.erb +++ b/app/views/order_products/_total_price.html.erb @@ -1,8 +1,10 @@ -<%= f.label :total_price %> -
- - <%= f.number_field :total_price, step: :any, class: 'form-control input-lg' %> - - <%= f.submit "Order!", class: "btn btn-primary input-lg" %> - +
+ <%= f.label :total_price %> +
+ + <%= f.number_field :total_price, step: :any, class: 'form-control input-lg' %> + + <%= f.submit "Order!", class: "btn btn-primary input-lg" %> + +
diff --git a/app/views/orders/_order.html.erb b/app/views/orders/_order.html.erb index aead806..3c42853 100644 --- a/app/views/orders/_order.html.erb +++ b/app/views/orders/_order.html.erb @@ -1,6 +1,2 @@ <%= order.created_at %> -

- <% products.each do |product| %> - <%= pluralize(product.count, product.name) %> - <% end %> -

+<%= simple_format(products.map { |p| pluralize(p.count, p.name) }.to_sentence) %> diff --git a/app/views/orders/_overview.html.erb b/app/views/orders/_overview.html.erb new file mode 100644 index 0000000..8d390ee --- /dev/null +++ b/app/views/orders/_overview.html.erb @@ -0,0 +1,6 @@ +
+

sort by name

+ <% users.each do |user| %> + <%= render 'users/new_order', user: user %> + <% end %> +
diff --git a/app/views/orders/_user_list.html.erb b/app/views/orders/_user_list.html.erb deleted file mode 100644 index 6a3fb7a..0000000 --- a/app/views/orders/_user_list.html.erb +++ /dev/null @@ -1,9 +0,0 @@ -<% users.each do |user| %> -
- <%= link_to image_tag(user.dagschotel.avatar, class: "img-circle dagschotel"), user_quickpay_path(user) unless user.dagschotel.nil? %> - <%= link_to image_tag(user.avatar , class: "img-circle avatar"), new_user_order_path(user) %> - - <%= link_to user.name , new_user_order_path(user), class: "btn btn-info", - style: get_color_style(user) %> -
-<% end %> diff --git a/app/views/orders/new.html.erb b/app/views/orders/new.html.erb index 916e9d9..5edd471 100644 --- a/app/views/orders/new.html.erb +++ b/app/views/orders/new.html.erb @@ -6,13 +6,10 @@
<%= f.fields_for :order_products do |op_field| %> - <%= render 'order_products/form_row', f: op_field %> + <%= render op_field.object, f: op_field, product: op_field.object.product %> <% end %>
-
- <%= render 'order_products/total_price', f: f %> -
- -<% end %> + <%= render 'order_products/total_price', f: f %> + <% end %>
diff --git a/app/views/orders/overview.html.erb b/app/views/orders/overview.html.erb index 4ba80cf..ed6fc68 100644 --- a/app/views/orders/overview.html.erb +++ b/app/views/orders/overview.html.erb @@ -1,11 +1,4 @@ <%= render partial: 'flash' %> -
-

sort by name

- <%= render 'orders/user_list', users: @users_by_name %> -
- -
-

sort by order

- <%= render 'orders/user_list', users: @users_by_order %> -
+<%= render 'overview', users: @users_by_name %> +<%= render 'overview', users: @users_by_order %> diff --git a/app/views/products/_category.html.erb b/app/views/products/_category.html.erb index e86381c..7f92718 100644 --- a/app/views/products/_category.html.erb +++ b/app/views/products/_category.html.erb @@ -1,3 +1 @@ -

- <%= pluralize(category.count, category.category) %> -

+<%= simple_format(pluralize(category.count, category.category)) %> diff --git a/app/views/products/_form.html.erb b/app/views/products/_form.html.erb index b44fd45..ac6a4b5 100644 --- a/app/views/products/_form.html.erb +++ b/app/views/products/_form.html.erb @@ -10,6 +10,9 @@ <%= form_collection_select f, :category, Product.categories.keys, :to_s, :titlecase %> + <%= f.label :stock %> + <%= f.number_field :stock, class: 'form-control form-field' %> + <%= f.label :avatar %> <%= f.file_field :avatar , class: "form-field" %> diff --git a/app/views/products/_product.html.erb b/app/views/products/_product.html.erb index a82eced..36e58dd 100644 --- a/app/views/products/_product.html.erb +++ b/app/views/products/_product.html.erb @@ -3,10 +3,12 @@ <%= image_tag product.avatar %>

<%= product.name %> - <%= euro(product.price) %>

-

- <%= link_to "Edit", edit_product_path(product), class: "btn btn-default" %> - <%= link_to "Delete", product_path(product), method: :delete, class: "btn btn-danger", data: {confirm: 'Are you sure?'} %> -

+ <% if current_user.admin? %> +

+ <%= link_to "Edit", edit_product_path(product), class: "btn btn-default" %> + <%= link_to "Delete", product_path(product), method: :delete, class: "btn btn-danger", data: {confirm: 'Are you sure?'} %> +

+ <% end %>
diff --git a/app/views/products/_product_row.html.erb b/app/views/products/_product_row.html.erb index dcc241d..cc1e384 100644 --- a/app/views/products/_product_row.html.erb +++ b/app/views/products/_product_row.html.erb @@ -1,3 +1 @@ -

- <%= pluralize(product.count, product.name) %> -

+<%= simple_format(pluralize(product.count, product.name)) %> diff --git a/app/views/users/_new_order.html.erb b/app/views/users/_new_order.html.erb new file mode 100644 index 0000000..4d9a7c9 --- /dev/null +++ b/app/views/users/_new_order.html.erb @@ -0,0 +1,7 @@ +
+ <%= link_to image_tag(user.dagschotel.avatar, class: "img-circle dagschotel"), user_quickpay_path(user) unless user.dagschotel.nil? %> + <%= link_to image_tag(user.avatar , class: "img-circle avatar"), new_user_order_path(user) %> + + <%= link_to user.name , new_user_order_path(user), class: "btn btn-info", + style: get_color_style(user) %> +
diff --git a/app/views/users/_user.html.erb b/app/views/users/_user.html.erb index 6f8436e..2fc8bda 100644 --- a/app/views/users/_user.html.erb +++ b/app/views/users/_user.html.erb @@ -1,6 +1,6 @@
-

<%= user.full_name %>

+

<%= user.full_name %>

<%= image_tag(user.avatar , class: "img-circle avatar") %>

Name: <%= user.name %>

diff --git a/db/migrate/20150113155744_add_stock_to_products.rb b/db/migrate/20150113155744_add_stock_to_products.rb new file mode 100644 index 0000000..115a4ce --- /dev/null +++ b/db/migrate/20150113155744_add_stock_to_products.rb @@ -0,0 +1,5 @@ +class AddStockToProducts < ActiveRecord::Migration + def change + add_column :products, :stock, :integer, default: 0 + end +end diff --git a/db/schema.rb b/db/schema.rb index 7ca2d12..2cd70b9 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20141217063222) do +ActiveRecord::Schema.define(version: 20150113155744) do create_table "order_products", force: true do |t| t.integer "order_id" @@ -39,6 +39,7 @@ ActiveRecord::Schema.define(version: 20141217063222) do t.integer "avatar_file_size" t.datetime "avatar_updated_at" t.integer "category", default: 0 + t.integer "stock", default: 0 end create_table "users", force: true do |t| diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml index 6de2af1..0947a20 100644 --- a/test/fixtures/products.yml +++ b/test/fixtures/products.yml @@ -12,6 +12,7 @@ # avatar_file_size :integer # avatar_updated_at :datetime # category :integer default(0) +# stock :integer default(0) # # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index 640f298..8ae255c 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -23,6 +23,7 @@ # avatar_file_size :integer # avatar_updated_at :datetime # orders_count :integer default(0) +# koelkast :boolean default(FALSE) # # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html diff --git a/test/models/product_test.rb b/test/models/product_test.rb index e089dca..0e4c013 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -12,6 +12,7 @@ # avatar_file_size :integer # avatar_updated_at :datetime # category :integer default(0) +# stock :integer default(0) # require 'test_helper' diff --git a/test/models/user_test.rb b/test/models/user_test.rb index 086c7cf..24c088a 100644 --- a/test/models/user_test.rb +++ b/test/models/user_test.rb @@ -23,6 +23,7 @@ # avatar_file_size :integer # avatar_updated_at :datetime # orders_count :integer default(0) +# koelkast :boolean default(FALSE) # require 'test_helper'