diff --git a/app/controllers/concerns/statistics.rb b/app/controllers/concerns/statistics.rb new file mode 100644 index 0000000..31f8d1f --- /dev/null +++ b/app/controllers/concerns/statistics.rb @@ -0,0 +1,24 @@ +module Statistics + extend ActiveSupport::Concern + + def products_group_by_category + products + .select("products.category", "sum(order_items.count) as count") + .group(:category) + end + + def all_orders page + orders + .order(:created_at) + .reverse_order + .paginate(page: page) + end + + def products_group_by_id + products + .select("products.*", "sum(order_items.count) as count") + .group(:product_id) + .order("count") + .reverse_order + end +end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 0269690..e9df136 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -1,13 +1,12 @@ class OrdersController < ApplicationController - include ActionView::Helpers::NumberHelper - include ApplicationHelper - load_resource :user load_and_authorize_resource :order, through: :user, shallow: true def new products = (@user.products.for_sale.select("products.*", "sum(order_items.count) as count").group(:product_id).order("count desc") | Product.for_sale) - @order.g_order_items products + products.each do |p| + @order.order_items.build(product: p) + end end def create @@ -29,18 +28,6 @@ class OrdersController < ApplicationController @users = User.members.publik.order(:name) end - def quickpay - user = User.find(params[:id]) - order = user.orders.build - order.order_items << OrderItem.new(count: 1, product: user.dagschotel, order: order) - if order.save - flash[:success] = "Quick pay succeeded. #{view_context.link_to("Undo", [user, order], method: :delete)}." - else - flash[:error] = order.errors.full_messages.first - end - redirect_to root_path - end - private def order_params diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 3975675..ab472b4 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -4,11 +4,9 @@ class ProductsController < ApplicationController respond_to :html, :js def new - @product = Product.new end def create - @product = Product.new(product_params) if @product.save flash[:success] = "Product created!" redirect_to products_path @@ -25,12 +23,10 @@ class ProductsController < ApplicationController end def edit - @product = Product.find(params[:id]) respond_with @product end def update - @product = Product.find(params[:id]) @product.update_attributes product_params respond_with @product end diff --git a/app/controllers/stocks_controller.rb b/app/controllers/stocks_controller.rb index 9fc8b1c..8c48044 100644 --- a/app/controllers/stocks_controller.rb +++ b/app/controllers/stocks_controller.rb @@ -2,7 +2,6 @@ class StocksController < ApplicationController load_and_authorize_resource def new - @stock = Stock.new Product.all.each do |p| @stock.stock_entries << Stock::StockEntry.new(product: p) end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 6d159e7..71475ee 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,11 +1,8 @@ class UsersController < ApplicationController load_and_authorize_resource - before_action :init, only: [:show, :edit, :update] + before_action :init, only: :show def show - @categories = @user.products - .select("products.category", "sum(order_items.count) as count") - .group(:category) end def edit @@ -26,15 +23,12 @@ class UsersController < ApplicationController end def destroy - user = User.find(params[:id]) - user.destroy + @user.destroy flash[:success] = "Succesfully removed user" redirect_to users_path end def edit_dagschotel - @user = User.find(params[:id]) - authorize! :update_dagschotel, @user @dagschotel = @user.dagschotel @products = Product.for_sale @@ -42,14 +36,22 @@ class UsersController < ApplicationController end def update_dagschotel - user = User.find(params[:id]) - authorize! :update_dagschotel, user - - user.dagschotel = Product.find(params[:product_id]) - user.save + @user.dagschotel = Product.find(params[:product_id]) + @user.save flash[:success] = "Succesfully updated dagschotel" - redirect_to user + redirect_to @user + end + + def quickpay + order = @user.orders.build + order.order_items.build(count: 1, product: user.dagschotel) + if order.save + flash[:success] = "Quick pay succeeded. #{view_context.link_to("Undo", [user, order], method: :delete)}." + else + flash[:error] = order.errors.full_messages.first + end + redirect_to root_path end private @@ -60,14 +62,5 @@ class UsersController < ApplicationController def init @user = User.find_by_id(params[:id]) || current_user - @orders = @user.orders - .order(:created_at) - .reverse_order - .paginate(page: params[:page]) - @products = @user.products - .select("products.*", "sum(order_items.count) as count") - .group(:product_id) - .order("count") - .reverse_order end end diff --git a/app/helpers/callbacks_helper.rb b/app/helpers/callbacks_helper.rb deleted file mode 100644 index 6c9550c..0000000 --- a/app/helpers/callbacks_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module CallbacksHelper -end diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb deleted file mode 100644 index 309f8b2..0000000 --- a/app/helpers/sessions_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module SessionsHelper -end diff --git a/app/helpers/stock_helper.rb b/app/helpers/stock_helper.rb deleted file mode 100644 index db18c80..0000000 --- a/app/helpers/stock_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module StockHelper -end diff --git a/app/helpers/welcome_helper.rb b/app/helpers/welcome_helper.rb deleted file mode 100644 index eeead45..0000000 --- a/app/helpers/welcome_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module WelcomeHelper -end diff --git a/app/jobs/tab_api_job.rb b/app/jobs/tab_api_job.rb index 3b66796..2137af2 100644 --- a/app/jobs/tab_api_job.rb +++ b/app/jobs/tab_api_job.rb @@ -2,8 +2,18 @@ TabApiJob = Struct.new(:order_id) do def perform(*args) order = Order.find_by(id: order_id) if order && !order.transaction_id - body = { transaction: { debtor: order.user.uid, cents: order.price_cents, message: order.to_sentence, id_at_client: order.id } } - headers = { "Authorization" => "Token token=#{Rails.application.secrets.tab_api_key}" } + body = { + transaction: { + debtor: order.user.uid, + cents: order.price_cents, + message: order.to_sentence, + id_at_client: order.id + } + } + headers = { + "Authorization" => "Token token=#{Rails.application.secrets.tab_api_key}" + } + result = HTTParty.post("https://zeus.ugent.be/tab/transactions", body: body, headers: headers ) order.update_attribute(:transaction_id, JSON.parse(result.body)["id"].to_i) end diff --git a/app/models/ability.rb b/app/models/ability.rb index 1cd5ad1..3879a9c 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -2,18 +2,21 @@ class Ability include CanCan::Ability def initialize(user) - user ||= User.new # guest user (not logged in) + return unless user if user.admin? can :manage, :all elsif user.koelkast? can :manage, Order - elsif user[:id] + else can :read, :all can :manage, User, id: user.id - can :manage, Order do |order| + can :create, Order do |order| order.try(:user) == user end + can :delete, Order do |order| + order.try(:user) == user && order.created_at > Rails.application.config.call_api_after.ago + end end end end diff --git a/app/models/order.rb b/app/models/order.rb index 20fe86c..146503a 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -10,7 +10,6 @@ # transaction_id :integer # -require 'httparty' class Order < ActiveRecord::Base include ActionView::Helpers::TextHelper @@ -20,11 +19,12 @@ class Order < ActiveRecord::Base before_validation :calculate_price before_save { |o| o.order_items = o.order_items.reject{ |oi| oi.count == 0 } } - after_create { Delayed::Job.enqueue TabApiJob.new(id) } + after_create :create_api_job validates :user, presence: true - validates :order_items, presence: true, in_stock: true + validates :order_items, presence: true validates :price_cents, presence: true + validates_associated :order_items accepts_nested_attributes_for :order_items @@ -34,15 +34,17 @@ class Order < ActiveRecord::Base }.to_sentence end - def g_order_items(products) - products.each do |p| - self.order_items.build(product: p) - end - end - private - def calculate_price - self.price_cents = self.order_items.map{ |oi| oi.count * oi.product.price_cents }.sum - end + def calculate_price + self.price_cents = self.order_items.map{ |oi| oi.count * oi.product.price_cents }.sum + end + + def create_api_job + priority = 0 + run_at = Rails.application.config.call_api_after.from_now + job = TabApiJob.new(id) + + Delayed::Job.enqueue job, priority, run_at + end end diff --git a/app/models/order_item.rb b/app/models/order_item.rb index 0e809b8..3a82226 100644 --- a/app/models/order_item.rb +++ b/app/models/order_item.rb @@ -13,25 +13,31 @@ class OrderItem < ActiveRecord::Base belongs_to :product validates :product, presence: true - validates :count, presence: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 } + validates :count, presence: true, numericality: { only_integer: true, + less_than_or_equal_to: ->(oi) { oi.product.stock }, + greater_than_or_equal_to: 0 } - before_destroy :put_back_in_stock - after_create :remove_from_stock + before_destroy :put_back_in_stock! + after_create :remove_from_stock! accepts_nested_attributes_for :product def product_attributes=(attributes) - self.product = Product.find(attributes[:id]) + self.product = OrderItem.products.select{ |p| p.id == attributes[:id].to_i }.first super end + def self.products + @products || Product.all + end + private - def remove_from_stock + def remove_from_stock! product.decrement!(:stock, count) end - def put_back_in_stock + def put_back_in_stock! product.increment!(:stock, self.count) end end diff --git a/app/models/product.rb b/app/models/product.rb index ec99a18..d455f37 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -42,7 +42,7 @@ class Product < ActiveRecord::Base self.price_cents = (value.to_f * 100).to_int end - def out_of_sale + def take_out_of_sale! update_attribute :deleted, true end end diff --git a/app/models/user.rb b/app/models/user.rb index c9a997c..86266c4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -27,6 +27,8 @@ require 'identicon' class User < ActiveRecord::Base + include Statistics + devise :database_authenticatable, :trackable, :omniauthable, :omniauth_providers => [:zeuswpi] has_paper_trail diff --git a/app/validators/in_stock_validator.rb b/app/validators/in_stock_validator.rb deleted file mode 100644 index ee7f3e3..0000000 --- a/app/validators/in_stock_validator.rb +++ /dev/null @@ -1,9 +0,0 @@ -class InStockValidator < ActiveModel::Validator - def validate(record) - p_short = [] - record.order_items.each do |oi| - p_short.append oi.product.name if oi.count > oi.product.stock - end - record.errors.add(:base, "There is not enough stock for your order of the following products: #{p_short.join(', ')}") if p_short.size > 0 - end -end diff --git a/app/views/orders/_order.html.erb b/app/views/orders/_order.html.erb index f123b18..7c62b58 100644 --- a/app/views/orders/_order.html.erb +++ b/app/views/orders/_order.html.erb @@ -8,7 +8,6 @@ <%= order.to_sentence %> - <% p order %> <%= euro_from_cents(order.price_cents) %> diff --git a/app/views/users/_sidebar.html.erb b/app/views/users/_sidebar.html.erb index 0e8cc72..dd55613 100644 --- a/app/views/users/_sidebar.html.erb +++ b/app/views/users/_sidebar.html.erb @@ -11,7 +11,7 @@