diff --git a/app/controllers/barcodes_controller.rb b/app/controllers/barcodes_controller.rb index 9318d2c..f8c7ed2 100644 --- a/app/controllers/barcodes_controller.rb +++ b/app/controllers/barcodes_controller.rb @@ -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!" diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index ace4c01..b757ef8 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -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 diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 6ec7ddf..858ce25 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -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 diff --git a/app/models/ability.rb b/app/models/ability.rb index 416a8db..047deee 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -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 diff --git a/app/models/barcode.rb b/app/models/barcode.rb index c3e34ed..80e595f 100644 --- a/app/models/barcode.rb +++ b/app/models/barcode.rb @@ -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 diff --git a/app/models/order_item.rb b/app/models/order_item.rb index 45adfac..d8aa2c0 100644 --- a/app/models/order_item.rb +++ b/app/models/order_item.rb @@ -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! diff --git a/app/views/orders/new.html.haml b/app/views/orders/new.html.haml index 3f697af..a8632e3 100644 --- a/app/views/orders/new.html.haml +++ b/app/views/orders/new.html.haml @@ -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 diff --git a/db/migrate/20151028223229_add_default_false_to_admin_users.rb b/db/migrate/20151028223229_add_default_false_to_admin_users.rb new file mode 100644 index 0000000..27285c1 --- /dev/null +++ b/db/migrate/20151028223229_add_default_false_to_admin_users.rb @@ -0,0 +1,5 @@ +class AddDefaultFalseToAdminUsers < ActiveRecord::Migration + def change + change_column :users, :admin, :boolean, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index a8562ce..3640807 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: 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" diff --git a/spec/controllers/products_controller_spec.rb b/spec/controllers/products_controller_spec.rb index c9808b5..35bb79d 100644 --- a/spec/controllers/products_controller_spec.rb +++ b/spec/controllers/products_controller_spec.rb @@ -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 diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index d394019..4c4af9c 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -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 diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 0225022..11397b8 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -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 diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index c480786..77813ff 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -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) } diff --git a/spec/models/barcode_spec.rb b/spec/models/barcode_spec.rb index d2389d7..77acc1a 100644 --- a/spec/models/barcode_spec.rb +++ b/spec/models/barcode_spec.rb @@ -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 diff --git a/spec/models/order_item_spec.rb b/spec/models/order_item_spec.rb index 72a2cb6..73b3fe6 100644 --- a/spec/models/order_item_spec.rb +++ b/spec/models/order_item_spec.rb @@ -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 diff --git a/spec/models/order_spec.rb b/spec/models/order_spec.rb index 3e46b83..0c49692 100644 --- a/spec/models/order_spec.rb +++ b/spec/models/order_spec.rb @@ -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 diff --git a/spec/models/product_spec.rb b/spec/models/product_spec.rb index e009912..abf6e74 100644 --- a/spec/models/product_spec.rb +++ b/spec/models/product_spec.rb @@ -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 diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 9ed782f..b18e6d1 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -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