commit
f089653f0f
18 changed files with 292 additions and 103 deletions
|
@ -1,6 +1,7 @@
|
|||
class BarcodesController < ApplicationController
|
||||
load_and_authorize_resource :product, only: :create
|
||||
load_and_authorize_resource :barcode, through: :product, shallow: true
|
||||
|
||||
def create
|
||||
@barcode.save
|
||||
redirect_to barcode_products_path, notice: "Barcode successfully linked!"
|
||||
|
|
|
@ -31,6 +31,6 @@ class OrdersController < ApplicationController
|
|||
private
|
||||
|
||||
def order_params
|
||||
params.require(:order).permit(order_items_attributes: [:count, :price, product_attributes: [:id]])
|
||||
params.require(:order).permit(order_items_attributes: [:count, :price, :product_id])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,21 +29,9 @@ class UsersController < ApplicationController
|
|||
order = @user.orders.build
|
||||
order.order_items.build(count: 1, product: @user.dagschotel)
|
||||
if order.save
|
||||
respond_to do |format|
|
||||
format.js { render json: { message: "Quick pay succeeded for #{@user.name}." }, status: :ok }
|
||||
format.html {
|
||||
flash[:success] = "Quick pay succeeded."
|
||||
redirect_to root_path
|
||||
}
|
||||
end
|
||||
render json: { message: "Quick pay succeeded for #{@user.name}." }, status: :ok
|
||||
else
|
||||
respond_to do |format|
|
||||
format.js { head :unprocessable_entity }
|
||||
format.html {
|
||||
flash[:error] = order.errors.full_messages.first
|
||||
redirect_to root_path
|
||||
}
|
||||
end
|
||||
head :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,24 +4,32 @@ class Ability
|
|||
def initialize(user)
|
||||
return unless user
|
||||
|
||||
can :read, Barcode
|
||||
initialize_admin if user.admin?
|
||||
initialize_koelkast if user.koelkast?
|
||||
initialize_user(user)
|
||||
|
||||
if user.admin?
|
||||
can :manage, :all
|
||||
elsif user.koelkast?
|
||||
can :manage, Order do |order|
|
||||
!order.try(:user).try(:private)
|
||||
end
|
||||
can :quickpay, User
|
||||
else
|
||||
can :read, :all
|
||||
can :manage, User, id: user.id
|
||||
can :create, Order do |order|
|
||||
order.try(:user) == user
|
||||
end
|
||||
can :destroy, Order do |order|
|
||||
order.try(:user) == user && order.deletable
|
||||
end
|
||||
can :read, Barcode
|
||||
end
|
||||
|
||||
def initialize_admin
|
||||
can :manage, :all
|
||||
end
|
||||
|
||||
def initialize_koelkast
|
||||
can :manage, Order do |order|
|
||||
!order.try(:user).try(:private)
|
||||
end
|
||||
can :quickpay, User
|
||||
end
|
||||
|
||||
def initialize_user(user)
|
||||
can :read, :all
|
||||
can :manage, User, id: user.id
|
||||
can :create, Order do |order|
|
||||
order.try(:user) == user
|
||||
end
|
||||
can :destroy, Order do |order|
|
||||
order.try(:user) == user && order.deletable
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,6 +15,6 @@ class Barcode < ActiveRecord::Base
|
|||
|
||||
belongs_to :product
|
||||
|
||||
# validates :product, presence: true
|
||||
validates :product, presence: true
|
||||
validates :code, presence: true, uniqueness: true
|
||||
end
|
||||
|
|
|
@ -20,17 +20,6 @@ class OrderItem < ActiveRecord::Base
|
|||
before_destroy :put_back_in_stock!
|
||||
after_create :remove_from_stock!
|
||||
|
||||
accepts_nested_attributes_for :product
|
||||
|
||||
def product_attributes=(attributes)
|
||||
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!
|
||||
|
|
|
@ -19,8 +19,7 @@
|
|||
%tr.order_item_wrapper{ data: { product: ff.object.product.id, price: ff.object.product.price_cents } }
|
||||
%td
|
||||
= ff.number_field :count
|
||||
= ff.fields_for :product do |fff|
|
||||
/ Needed for haml
|
||||
= ff.hidden_field :product_id
|
||||
%td
|
||||
x
|
||||
%td
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
class AddDefaultFalseToAdminUsers < ActiveRecord::Migration
|
||||
def change
|
||||
change_column :users, :admin, :boolean, default: false
|
||||
end
|
||||
end
|
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20150919091214) do
|
||||
ActiveRecord::Schema.define(version: 20151028223229) do
|
||||
|
||||
create_table "barcodes", force: :cascade do |t|
|
||||
t.integer "product_id"
|
||||
|
@ -75,7 +75,7 @@ ActiveRecord::Schema.define(version: 20150919091214) do
|
|||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.datetime "remember_created_at"
|
||||
t.boolean "admin"
|
||||
t.boolean "admin", default: false
|
||||
t.integer "dagschotel_id"
|
||||
t.string "avatar_file_name"
|
||||
t.string "avatar_content_type"
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# from_barcode_products POST /products/barcode(.:format) products#from_barcode
|
||||
# products GET /products(.:format) products#index
|
||||
# POST /products(.:format) products#create
|
||||
# new_product GET /products/new(.:format) products#new
|
||||
# edit_product GET /products/:id/edit(.:format) products#edit
|
||||
# product PATCH /products/:id(.:format) products#update
|
||||
# PUT /products/:id(.:format) products#update
|
||||
# barcode_products GET /products/barcode(.:format) products#barcode
|
||||
# load_barcode_products POST /products/barcode(.:format) products#load_barcode
|
||||
# products GET /products(.:format) products#index
|
||||
# POST /products(.:format) products#create
|
||||
# edit_product GET /products/:id/edit(.:format) products#edit
|
||||
# product PATCH /products/:id(.:format) products#update
|
||||
# PUT /products/:id(.:format) products#update
|
||||
#
|
||||
|
||||
describe ProductsController, type: :controller do
|
||||
|
@ -13,24 +13,6 @@ describe ProductsController, type: :controller do
|
|||
sign_in @admin
|
||||
end
|
||||
|
||||
#########
|
||||
# NEW #
|
||||
#########
|
||||
|
||||
describe 'GET new' do
|
||||
it 'should render the form' do
|
||||
get :new
|
||||
expect(response).to render_template(:new)
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'should initialize a new product' do
|
||||
get :new
|
||||
expect(assigns(:product).class).to eq(Product)
|
||||
expect(assigns(:product)).to_not be_persisted
|
||||
end
|
||||
end
|
||||
|
||||
##########
|
||||
# POST #
|
||||
##########
|
||||
|
@ -43,7 +25,7 @@ describe ProductsController, type: :controller do
|
|||
}.to change{ Product.count }.by(1)
|
||||
end
|
||||
|
||||
it 'should redirect to index page' do
|
||||
it 'should redirect to barcode page' do
|
||||
post :create, product: attributes_for(:product)
|
||||
expect(response).to redirect_to action: :barcode
|
||||
end
|
||||
|
@ -82,16 +64,18 @@ describe ProductsController, type: :controller do
|
|||
describe 'GET edit' do
|
||||
before :each do
|
||||
@product = create :product
|
||||
get :edit, id: @product
|
||||
end
|
||||
|
||||
it 'should render the correct form' do
|
||||
get :edit, id: @product
|
||||
expect(response).to render_template(:edit)
|
||||
it 'should be successful' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'should render the correct form' do
|
||||
expect(response).to render_template(:edit)
|
||||
end
|
||||
|
||||
it 'should load the correct product' do
|
||||
get :edit, id: @product
|
||||
expect(assigns :product).to eq(@product)
|
||||
end
|
||||
end
|
||||
|
@ -106,7 +90,7 @@ describe ProductsController, type: :controller do
|
|||
end
|
||||
|
||||
it 'loads right product' do
|
||||
put :edit, id: @product, product: attributes_for(:product)
|
||||
put :update, id: @product, product: attributes_for(:product)
|
||||
expect(assigns :product).to eq(@product)
|
||||
end
|
||||
|
||||
|
@ -119,23 +103,69 @@ describe ProductsController, type: :controller do
|
|||
|
||||
context 'failed' do
|
||||
it 'should not update attributes' do
|
||||
old_attributes = @product.attributes
|
||||
old_price = @product.price
|
||||
put :update, id: @product, product: attributes_for(:invalid_product)
|
||||
expect(@product.reload.attributes).to eq(old_attributes)
|
||||
expect(@product.reload.price).to eq(old_price)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#############
|
||||
# BARCODE #
|
||||
#############
|
||||
|
||||
describe 'GET barcode' do
|
||||
it 'should be successful' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
##################
|
||||
# FROM_BARCODE #
|
||||
# LOAD_BARCODE #
|
||||
##################
|
||||
|
||||
describe 'POST from_barcode' do
|
||||
it 'should return a product when barcode in database' do
|
||||
product = create :product
|
||||
bar = create :barcode, product: product
|
||||
post :from_barcode, barcode: bar.code
|
||||
expect(JSON.parse(response.body)["id"]).to eq(product.id)
|
||||
describe 'POST load_barcode' do
|
||||
describe 'new barcode' do
|
||||
before :each do
|
||||
@code = attributes_for(:barcode)[:code].to_s
|
||||
post :load_barcode, barcode: @code
|
||||
end
|
||||
|
||||
it 'should be successful' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'should be render the link partial' do
|
||||
expect(response).to render_template(:link)
|
||||
end
|
||||
|
||||
it 'should allow building a new product' do
|
||||
expect(assigns(:product).id).to be nil
|
||||
end
|
||||
|
||||
it 'should have a barcode built for the new product' do
|
||||
barcode = assigns(:product).barcodes.first
|
||||
expect(barcode.code).to eq @code
|
||||
end
|
||||
end
|
||||
|
||||
describe 'existing barcode' do
|
||||
before :each do
|
||||
@barcode = create :barcode
|
||||
post :load_barcode, barcode: @barcode.code
|
||||
end
|
||||
|
||||
it 'should be successful' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'should be render the stock_entry partial' do
|
||||
expect(response).to render_template(:stock_entry)
|
||||
end
|
||||
|
||||
it 'should have the correct product loaded' do
|
||||
expect(assigns :product).to eq @barcode.product
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# quickpay_user GET /users/:id/quickpay(.:format) users#quickpay
|
||||
# edit_dagschotel_user GET /users/:id/dagschotel/edit(.:format) users#edit_dagschotel
|
||||
# edit_user GET /users/:id/edit(.:format) users#edit
|
||||
# user GET /users/:id(.:format) users#show
|
||||
# PATCH /users/:id(.:format) users#update
|
||||
# PUT /users/:id(.:format) users#update
|
||||
# quickpay_user GET /users/:id/quickpay(.:format) users#quickpay
|
||||
# edit_dagschotel_user GET /users/:id/dagschotel/edit(.:format) users#edit_dagschotel
|
||||
# edit_user GET /users/:id/edit(.:format) users#edit
|
||||
# user GET /users/:id(.:format) users#show
|
||||
# PATCH /users/:id(.:format) users#update
|
||||
# PUT /users/:id(.:format) users#update
|
||||
#
|
||||
|
||||
describe UsersController, type: :controller do
|
||||
|
@ -22,10 +22,13 @@ describe UsersController, type: :controller do
|
|||
end
|
||||
|
||||
it 'should be successful' do
|
||||
expect(response).to render_template(:show)
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'should render the user' do
|
||||
expect(response).to render_template(:show)
|
||||
end
|
||||
|
||||
it 'should load the correct user' do
|
||||
expect(assigns(:user)).to eq(@user)
|
||||
end
|
||||
|
@ -40,6 +43,10 @@ describe UsersController, type: :controller do
|
|||
get :edit, id: @user
|
||||
end
|
||||
|
||||
it 'should be successful' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'should render the form' do
|
||||
expect(response).to render_template(:edit)
|
||||
end
|
||||
|
@ -79,10 +86,73 @@ describe UsersController, type: :controller do
|
|||
#####################
|
||||
|
||||
describe 'GET edit_dagschotel' do
|
||||
it 'should be successful' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'should render the page' do
|
||||
get :edit_dagschotel, id: @user
|
||||
expect(response).to render_template(:edit_dagschotel)
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
##############
|
||||
# QUICKPAY #
|
||||
##############
|
||||
|
||||
describe 'GET quickpay' do
|
||||
describe 'successful' do
|
||||
before :each do
|
||||
@dagschotel = create :product, stock: 20
|
||||
@user.update_attribute(:dagschotel, @dagschotel)
|
||||
end
|
||||
|
||||
it 'should be successful' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'should make an order' do
|
||||
expect{
|
||||
get :quickpay, id: @user
|
||||
}.to change{ @user.reload.orders_count }.by(1)
|
||||
end
|
||||
|
||||
describe 'order' do
|
||||
before :each do
|
||||
get :quickpay, id: @user
|
||||
@order = @user.orders.last
|
||||
end
|
||||
|
||||
it 'should contain 1 orderitem' do
|
||||
expect(@order.order_items.size).to eq 1
|
||||
end
|
||||
|
||||
it 'should have an orderitem with count 1' do
|
||||
expect(@order.order_items.first.count).to eq 1
|
||||
end
|
||||
|
||||
it 'should contain an orderitem for @dagschotel' do
|
||||
expect(@order.order_items.first.product).to eq @dagschotel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'failed' do
|
||||
before :each do
|
||||
@dagschotel = create :product, stock: 0
|
||||
@user.update_attribute(:dagschotel, @dagschotel)
|
||||
end
|
||||
|
||||
it 'should fail' do
|
||||
xhr :get, :quickpay, id: @user
|
||||
expect(response).to have_http_status(422)
|
||||
end
|
||||
|
||||
it 'should not make an order' do
|
||||
expect{
|
||||
get :quickpay, id: @user
|
||||
}.to_not change{ @user.reload.orders_count }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,8 +24,9 @@ require 'identicon'
|
|||
|
||||
FactoryGirl.define do
|
||||
factory :user do
|
||||
name { Faker::Name.name }
|
||||
avatar { Identicon.data_url_for name }
|
||||
name { Faker::Name.name }
|
||||
avatar { Identicon.data_url_for name }
|
||||
private { false }
|
||||
|
||||
factory :admin do
|
||||
admin true
|
||||
|
|
|
@ -21,13 +21,13 @@ describe User do
|
|||
let(:user) { create :user }
|
||||
|
||||
it{ should be_able_to(:create, Order.new(user: user)) }
|
||||
it{ should be_able_to(:delete, Order.new(user: user, created_at: (Rails.application.config.call_api_after - 1.minutes).ago)) }
|
||||
it{ should_not be_able_to(:delete, Order.new(user: user, created_at: 10.minutes.ago)) }
|
||||
it{ should be_able_to(:destroy, Order.new(user: user, created_at: (Rails.application.config.call_api_after - 1.minutes).ago)) }
|
||||
it{ should_not be_able_to(:destroy, Order.new(user: user, created_at: 10.minutes.ago)) }
|
||||
it{ should_not be_able_to(:create, Order.new) }
|
||||
it{ should_not be_able_to(:update, Order.new) }
|
||||
|
||||
it{ should be_able_to(:read, Product.new) }
|
||||
it{ should_not be_able_to(:delete, Product.new) }
|
||||
it{ should_not be_able_to(:destroy, Product.new) }
|
||||
it{ should_not be_able_to(:update, Product.new) }
|
||||
|
||||
it{ should_not be_able_to(:create, Stock.new) }
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: barcodes
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# product_id :integer
|
||||
# code :string default(""), not null
|
||||
# created_at :datetime
|
||||
# updated_at :datetime
|
||||
#
|
||||
|
||||
describe Barcode do
|
||||
before :each do
|
||||
@barcode = create :barcode
|
||||
|
@ -23,5 +34,12 @@ describe Barcode do
|
|||
expect(barcode).to_not be_valid
|
||||
end
|
||||
end
|
||||
|
||||
describe 'product' do
|
||||
it 'should be present' do
|
||||
@barcode.product = nil
|
||||
expect(@barcode).to_not be_valid
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -44,7 +44,7 @@ describe OrderItem do
|
|||
it 'should be less or equal to product stock' do
|
||||
@order_item.count = @order_item.product.stock + 1
|
||||
expect(@order_item).to_not be_valid
|
||||
@order_item.count = @order_item.product.stock
|
||||
@order_item.count = [@order_item.product.stock, 100].min
|
||||
expect(@order_item).to be_valid
|
||||
end
|
||||
end
|
||||
|
|
|
@ -26,7 +26,10 @@ describe Order do
|
|||
|
||||
describe 'fields' do
|
||||
describe 'user' do
|
||||
it { Order.reflect_on_association(:user).macro.should eq(:belongs_to) }
|
||||
it 'should be an association' do
|
||||
expect(Order.reflect_on_association(:user).macro).to eq(:belongs_to)
|
||||
end
|
||||
|
||||
it 'should be present' do
|
||||
@order.user = nil
|
||||
expect(@order).to_not be_valid
|
||||
|
@ -74,4 +77,24 @@ describe Order do
|
|||
end
|
||||
end
|
||||
|
||||
#############
|
||||
# HELPERS #
|
||||
#############
|
||||
|
||||
describe 'deletable' do
|
||||
it 'should be true' do
|
||||
@order.created_at = Rails.application.config.call_api_after.ago + 2.minutes
|
||||
expect(@order.deletable).to be true
|
||||
end
|
||||
|
||||
it 'should be false' do
|
||||
@order.created_at = Rails.application.config.call_api_after.ago - 2.minutes
|
||||
expect(@order.deletable).to be false
|
||||
end
|
||||
end
|
||||
|
||||
it 'sec_until_remove should return a number of seconds' do
|
||||
@order.created_at = Rails.application.config.call_api_after.ago + 2.minutes
|
||||
expect((@order.sec_until_remove - 120).abs).to be < 10
|
||||
end
|
||||
end
|
||||
|
|
|
@ -67,6 +67,11 @@ describe Product do
|
|||
expect(@product).to_not be_valid
|
||||
end
|
||||
|
||||
it 'should be a number' do
|
||||
@product.stock = "123abc"
|
||||
expect(@product).to_not be_valid
|
||||
end
|
||||
|
||||
it 'should be positive' do
|
||||
@product.stock = -5
|
||||
expect(@product).to_not be_valid
|
||||
|
@ -81,6 +86,11 @@ describe Product do
|
|||
expect(@product).to be_valid
|
||||
end
|
||||
|
||||
it 'should be a number' do
|
||||
@product.calories = "123abc"
|
||||
expect(@product).to_not be_valid
|
||||
end
|
||||
|
||||
it 'should be positive' do
|
||||
@product.calories = -5
|
||||
expect(@product).to_not be_valid
|
||||
|
@ -93,6 +103,12 @@ describe Product do
|
|||
expect(@product).to_not be_valid
|
||||
end
|
||||
end
|
||||
|
||||
describe 'deleted' do
|
||||
it 'should default false' do
|
||||
expect(@product.deleted).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#############
|
||||
|
@ -111,4 +127,15 @@ describe Product do
|
|||
end
|
||||
end
|
||||
|
||||
############
|
||||
# SCOPES #
|
||||
############
|
||||
|
||||
describe 'for sale' do
|
||||
it 'should return non-deleted products' do
|
||||
product = create :product
|
||||
product.update_attribute(:deleted, true)
|
||||
expect(Product.for_sale).to eq([@product])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -45,5 +45,35 @@ describe User do
|
|||
expect{ create :order, user: @user }.to change{ @user.reload.orders_count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'admin' do
|
||||
it 'should be false by default' do
|
||||
expect(@user.reload.admin).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe 'koelkast' do
|
||||
it 'should be false by default' do
|
||||
expect(@user.reload.koelkast).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
############
|
||||
# SCOPES #
|
||||
############
|
||||
|
||||
describe 'scopes' do
|
||||
it 'members should return members' do
|
||||
create :koelkast
|
||||
user = create :user
|
||||
expect(User.members).to eq([@user, user])
|
||||
end
|
||||
|
||||
it 'publik should return publik members' do
|
||||
user = create :user
|
||||
create :user, private: true
|
||||
expect(User.publik).to eq([@user, user])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue