This commit is contained in:
benji 2015-09-14 20:26:16 +02:00
parent de1436f5c7
commit b55ba47209
21 changed files with 102 additions and 97 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,2 +0,0 @@
module CallbacksHelper
end

View file

@ -1,2 +0,0 @@
module SessionsHelper
end

View file

@ -1,2 +0,0 @@
module StockHelper
end

View file

@ -1,2 +0,0 @@
module WelcomeHelper
end

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -27,6 +27,8 @@
require 'identicon'
class User < ActiveRecord::Base
include Statistics
devise :database_authenticatable, :trackable, :omniauthable, :omniauth_providers => [:zeuswpi]
has_paper_trail

View file

@ -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

View file

@ -8,7 +8,6 @@
<%= order.to_sentence %>
</td>
<td>
<% p order %>
<%= euro_from_cents(order.price_cents) %>
</td>
</tr>

View file

@ -11,7 +11,7 @@
<ul class="list-group">
<li class="list-group-item text-muted">Orders</li>
<li class="list-group-item"><strong>Orders placed</strong><span class="badge"><%= @user.orders_count %></span></li>
<li class="list-group-item"><strong>Products ordered</strong><span class="badge"><%= @products.map(&:count).sum %></span></li>
<li class="list-group-item"><strong>Products ordered</strong><span class="badge"><%= @user.products_group_by_id.map(&:count).sum %></span></li>
<% if can? :create, @user.orders.build %>
<li class="list-group-item"><%= link_to "Place new order", new_user_order_path(@user), class: "btn btn-default btn-block" %></li>
<% end %>

View file

@ -2,25 +2,25 @@
<div class="row">
<%= render 'sidebar' %>
<div id="user_info" class="col-sm-9">
<% if @orders.any? %>
<% if (all_orders = @user.all_orders(params[:page])).any? %>
<h4>Previously ordered</h4>
Total:
<ul>
<li>
<%= @categories.map{|c| pluralize(c.count, c.category)}.to_sentence %>
<%= @user.products_group_by_category.map{|c| pluralize(c.count, c.category)}.to_sentence %>
</li>
</ul>
Specifics:
<%= content_tag :ul do %>
<% @products.each do |p| %>
<% @user.products_group_by_id.each do |p| %>
<%= content_tag :li, pluralize(p.count, p.name) %>
<% end %>
<% end %>
<h4>All orders (<%= @user.orders_count %>)</h4>
<table class="orders"><%= render @orders %></table>
<%= will_paginate @orders %>
<table class="orders"><%= render all_orders %></table>
<%= will_paginate all_orders %>
</div>
<% end %>
</div>

View file

@ -21,5 +21,6 @@ module Tab002
# config.i18n.default_locale = :de
config.active_record.raise_in_transactional_callbacks = true
config.active_job.queue_adapter = :delayed_job
config.call_api_after = 5.minutes
end
end

View file

@ -18,17 +18,17 @@ Rails.application.routes.draw do
end
end
resources :users do
resources :orders
resources :users, only: [:show, :edit, :update, :destroy] do
resources :orders, only: [:new, :create, :destroy]
member do
get 'quickpay' => 'orders#quickpay'
get 'quickpay' => 'users#quickpay'
get 'dagschotel/edit' => 'users#edit_dagschotel', as: 'edit_dagschotel'
get 'dagschotel/:product_id' => 'users#update_dagschotel', as: 'dagschotel'
end
end
resources :products
resources :stocks
resources :products, only: [:new, :create, :index, :edit, :update]
resources :stocks, only: [:new, :create]
get 'overview' => 'orders#overview', as: "orders"
end