diff --git a/Gemfile b/Gemfile index 67e7c1d22a..155b940676 100644 --- a/Gemfile +++ b/Gemfile @@ -3,8 +3,6 @@ source 'https://rubygems.org' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '4.2.5' -# Use sqlite3 as the database for Active Record -gem 'sqlite3' # Use SCSS for stylesheets gem 'sass-rails', '~> 5.0' # Use Uglifier as compressor for JavaScript assets @@ -28,6 +26,8 @@ gem 'bcrypt', '~> 3.1.7' gem 'bootstrap-sass', '~> 3.3.6' +gem 'font-awesome-rails' + # Use Unicorn as the app server # gem 'unicorn' @@ -42,6 +42,10 @@ group :development, :test do gem 'hirb' end +group :production do + gem 'pg' +end + group :development do # Access an IRB console on exception pages or by using <%= console %> in views gem 'web-console', '~> 2.0' @@ -49,8 +53,9 @@ group :development do gem 'binding_of_caller' gem 'pry-rails' gem 'rails-erd' + # Use sqlite3 as the database for Active Record + gem 'sqlite3' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' end - diff --git a/Gemfile.lock b/Gemfile.lock index 6ef6bcd274..d0ca7b6dec 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -67,6 +67,8 @@ GEM docile (1.1.5) erubis (2.7.0) execjs (2.6.0) + font-awesome-rails (4.5.0.0) + railties (>= 3.2, < 5.0) globalid (0.3.6) activesupport (>= 4.1.0) hirb (0.7.3) @@ -90,6 +92,7 @@ GEM multi_json (1.11.2) nokogiri (1.6.7) mini_portile2 (~> 2.0.0.rc2) + pg (0.18.4) pry (0.10.3) coderay (~> 1.1.0) method_source (~> 0.8.1) @@ -199,9 +202,11 @@ DEPENDENCIES bootstrap-sass (~> 3.3.6) byebug coffee-rails (~> 4.1.0) + font-awesome-rails hirb jbuilder (~> 2.0) jquery-rails + pg pry-rails rails (= 4.2.5) rails-erd diff --git a/Procfile b/Procfile new file mode 100644 index 0000000000..c3936b2237 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: bundle exec rackup -p $PORT diff --git a/README.md b/README.md index cd2baba9d7..d344afba1a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ +TEST Team Quartzy Trelly Board https://trello.com/b/sBn5vXJY/quartzy +Heroku Link: +http://quartzy.herokuapp.com/ + # bEtsy [b]Etsy will be an online store where a wide variety of products can be listed and sold by any user. In this project we will focus on reinforcing the major components of Rails, Model Validation, as well as introducing some more complex logic such as user authentication. diff --git a/README.rdoc b/README.rdoc index dd4e97e22e..c8b858f49a 100644 --- a/README.rdoc +++ b/README.rdoc @@ -1,28 +1 @@ -== README - -This README would normally document whatever steps are necessary to get the -application up and running. - -Things you may want to cover: - -* Ruby version - -* System dependencies - -* Configuration - -* Database creation - -* Database initialization - -* How to run the test suite - -* Services (job queues, cache servers, search engines, etc.) - -* Deployment instructions - -* ... - - -Please feel free to use a different markup language if you do not plan to run -rake doc:app. +Find us on heroku: http://quartzy.herokuapp.com/ diff --git a/app/assets/images/quartzy.png b/app/assets/images/quartzy.png new file mode 100644 index 0000000000..10f82f239b Binary files /dev/null and b/app/assets/images/quartzy.png differ diff --git a/app/assets/javascripts/categories.coffee b/app/assets/javascripts/categories.coffee new file mode 100644 index 0000000000..24f83d18bb --- /dev/null +++ b/app/assets/javascripts/categories.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/categoryproducts.coffee b/app/assets/javascripts/categoryproducts.coffee new file mode 100644 index 0000000000..24f83d18bb --- /dev/null +++ b/app/assets/javascripts/categoryproducts.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/orderitems.coffee b/app/assets/javascripts/orderitems.coffee new file mode 100644 index 0000000000..24f83d18bb --- /dev/null +++ b/app/assets/javascripts/orderitems.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/orders.coffee b/app/assets/javascripts/orders.coffee new file mode 100644 index 0000000000..24f83d18bb --- /dev/null +++ b/app/assets/javascripts/orders.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/products.coffee b/app/assets/javascripts/products.coffee new file mode 100644 index 0000000000..24f83d18bb --- /dev/null +++ b/app/assets/javascripts/products.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/reviews.coffee b/app/assets/javascripts/reviews.coffee new file mode 100644 index 0000000000..24f83d18bb --- /dev/null +++ b/app/assets/javascripts/reviews.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/sessions.coffee b/app/assets/javascripts/sessions.coffee new file mode 100644 index 0000000000..24f83d18bb --- /dev/null +++ b/app/assets/javascripts/sessions.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/users.coffee b/app/assets/javascripts/users.coffee new file mode 100644 index 0000000000..24f83d18bb --- /dev/null +++ b/app/assets/javascripts/users.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/welcome.coffee b/app/assets/javascripts/welcome.coffee new file mode 100644 index 0000000000..24f83d18bb --- /dev/null +++ b/app/assets/javascripts/welcome.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index baccee21b4..205a5e36a7 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -1,2 +1,276 @@ @import "bootstrap-sprockets"; @import "bootstrap"; +@import "font-awesome"; + +$teal: #159E98; +$other-highlight: #218578; +$teal-grey: #32A69B; +$dark-teal: #238479; +$rust: #C18763; +$yellow: #D6D8A6; + +$light-contrast: $teal-grey; +$flash: #75E8E1; +$highlight: $teal; +$neutral: $yellow; + +/*$body: 'IM Fell DW Pica';*/ +$body: 'Tinos'; +$header: 'Tinos'; + +.each-merchant { + padding-bottom: 70px; +} + +.merchant-name { + padding-bottom: 20px; + text-align: center; + max-width: 380px; +} + +.centerBlock { + display: table; + margin: 0 auto; + margin-top: 20px; + margin-bottom: 20px; + } + +.product-names { + text-align: center; +} + +.emptycart { + text-align: center; +} + +.flash { + background-color: $flash; + text-align: center; + font-size: 16px; + padding: 5px; + margin: 5px; +} + +.front-pg { + text-align: center; + font-family: $body, serif; + font-size: 64px; +} + +.front-pg-link { + color: black; +} + +.header-box { + padding: 20px; + background-color: $light-contrast; + margin-bottom: 10px; + margin-top: 10px; +} + +.button-box { + padding-bottom: 25px; +} + +.col-xs-12 { + text-align: center; +} + +body { + font-family: $body, serif; +} + +.front-pg2 { + font-family: $header, serif; + text-align: center; + font-size: 20px; +} + +.jumbotron { + background-image: image-url("quartzy.png"); + background-size: cover; + +} + +.home_img { + display: block; + margin-left: auto; + margin-right: auto +} + +.cntr { + text-align: center; +} + +h1 { + font-family: $header, serif; + text-align: center; + margin-bottom: 20px; +} + +h2 { + font-family: $header, serif; +} + +h3 { + font-family: $header, serif; +} + +h4 { + font-family: $header, serif; +} + +h5 { + font-family: $header, serif; +} + +.cntr-header { + text-align: center; +} + +.navbar { + font-family: $header; + border:1px solid #ccc; + border-width:1px 0; + margin:0; + padding:15px; + text-align:center; + word-spacing: 10px; + text-transform: uppercase; +} + +.mark_shipped { + +} + +.cat-navbar { + +} + + +.category-box{ + margin: auto; + padding: 7px; + border: 1px solid $highlight; +} + +.product-page-img { + max-width: 250px; + max-height: 200px; + min-height: 200px; +} + +.cart-img { + max-width: 150px; + height: auto; + max-height: 200px; +} + +a { + color: $highlight; + text-decoration: none; +} + +a:hover { + color: $other-highlight; + text-decoration: none; +} + + +.table-master { + font-family: $body; + font-size: 17px; + +} + +.form-control { + width: 50%; + font-family: $body; + font-size: 17px; +} + +.form-group { + margin-left: 50px; +} + +.col-sm-4 { + margin: auto; + margin-bottom: 10px; +} + +.col-sm-6 { + margin-top: 20px; + text-align: center; + margin-left: auto; + margin-right: auto; +} + +.spacer { + margin: 10px; +} + +.rating { + list-style-image: none; +} + +.fa { + color: #FFD700; +} + +.btn { + font-size: 14px; + font-family: $header; + border: none; +} + +.center { + margin: auto; + display: block; +} + +.btn-success { + background-color: $dark-teal; +} + +.btn-success:hover { + background-color: $flash; +} + +.btn-success:active { + background-color: $flash; +} + +.btn-danger { + background-color: $rust; + border: none; +} + +.btn-default { + background-color: $other-highlight; + border: none; +} + +.btn-default:hover { + background-color: $rust; +} + +.btn-default:active { + background-color: $rust; +} + +.btn-info { + background-color: $teal; +} + +.rating-btn { + margin-top: 7px; +} + +.category_list { + padding: 0; + list-style-type: none; +} + +.dash-list { + list-style-type: none; +} diff --git a/app/assets/stylesheets/categories.scss b/app/assets/stylesheets/categories.scss new file mode 100644 index 0000000000..ef1657f8c9 --- /dev/null +++ b/app/assets/stylesheets/categories.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the categories controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/categoryproducts.scss b/app/assets/stylesheets/categoryproducts.scss new file mode 100644 index 0000000000..a89a1cd344 --- /dev/null +++ b/app/assets/stylesheets/categoryproducts.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the categoryproducts controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/orderitems.scss b/app/assets/stylesheets/orderitems.scss new file mode 100644 index 0000000000..3ae284dd37 --- /dev/null +++ b/app/assets/stylesheets/orderitems.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the orderitems controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/orders.scss b/app/assets/stylesheets/orders.scss new file mode 100644 index 0000000000..3b0428a94e --- /dev/null +++ b/app/assets/stylesheets/orders.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the orders controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss new file mode 100644 index 0000000000..89e2e8db07 --- /dev/null +++ b/app/assets/stylesheets/products.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the products controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/reviews.scss b/app/assets/stylesheets/reviews.scss new file mode 100644 index 0000000000..6ea2454d26 --- /dev/null +++ b/app/assets/stylesheets/reviews.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the reviews controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/sessions.scss b/app/assets/stylesheets/sessions.scss new file mode 100644 index 0000000000..7bef9cf826 --- /dev/null +++ b/app/assets/stylesheets/sessions.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the sessions controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/users.scss b/app/assets/stylesheets/users.scss new file mode 100644 index 0000000000..1efc835ccd --- /dev/null +++ b/app/assets/stylesheets/users.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the users controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/welcome.scss b/app/assets/stylesheets/welcome.scss new file mode 100644 index 0000000000..77ce11a740 --- /dev/null +++ b/app/assets/stylesheets/welcome.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the welcome controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d83690e1b9..6ecd527aa9 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,4 +2,59 @@ class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception + before_action :current_user + before_action :current_order + before_action :items_in_cart + + + def current_order + if session[:order_id] && !!Order.exists?(session[:order_id]) + @current_order ||= Order.find(session[:order_id]) + end + end + + def current_user + if session[:user_id] && !!User.exists?(session[:user_id]) + @current_user ||= User.find(session[:user_id]) + end + end + + def items_in_cart + if current_order + sum = [] + Order.find(session[:order_id]).orderitems.each do |oi| + sum.push(oi.quantity) + end + @cart_num = sum.inject(0) {|r, e| r + e } + else + @cart_num = 0 + end + end + + def require_login + if current_user.nil? + flash[:error] = "You must be logged in to view this section" + redirect_to new_session_path + end + end + + def navbar_categories + @navbar_cat = Category.where(user_id: nil) + end + + # checks that the user/:id, the :id is equal to current user + def only_current_user + if !@current_user || @current_user.id != params[:id].to_i + flash[:error] = "You are not authorized to view that section" + redirect_to root_path + end + end + + def current_user_owns_product + if current_user.id != Product.find(params[:id]).user_id + flash[:error] = "You are not authorized to view this section" + redirect_to :back + end + end + end diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb new file mode 100644 index 0000000000..41c67528af --- /dev/null +++ b/app/controllers/categories_controller.rb @@ -0,0 +1,36 @@ +class CategoriesController < ApplicationController +before_action :require_login, only: [:new, :create, :edit, :update] +before_action :navbar_categories, only: [:index, :show] + + def index + @cat = Category.all + end + def show + @category = Category.find(params[:id]) + end + def new + @category = Category.new + @action = "create" + end + def create + @category = Category.new(category_params) + @category.user_id = session[:user_id] + if @category.save + redirect_to user_products_dash_path(@category.user_id) + else + render :new + end + end + def edit + + end + def update + + end + + private + + def category_params + params.require(:category).permit(:name, :description) + end +end diff --git a/app/controllers/orderitems_controller.rb b/app/controllers/orderitems_controller.rb new file mode 100644 index 0000000000..d6e2b3ec97 --- /dev/null +++ b/app/controllers/orderitems_controller.rb @@ -0,0 +1,48 @@ +class OrderitemsController < ApplicationController + + #this method hooks up to button in cart to delete an orderitem, OR you might end up redirected here if you update at orderitem quantity to zero. + #if you are deleting the last item in the cart, the whole order gets deleted + def destroy + @orderitem = Orderitem.find(params[:id]) + @order = @orderitem.order + total_items = @order.orderitems + if total_items.count == 1 + @order = Order.find(session[:order_id]) + @order.destroy! + session[:order_id] = nil + redirect_to root_path + else + @orderitem.destroy + redirect_to cart_path + end + end + + + #happens in cart + #the only thing update can do is change the quantity + #a form will need to be sent for a particular orderitem on the cart page + #let them type in an integer, and if it's zero delete it + def update + @orderitem = Orderitem.find(params[:id]) + if orderitem_params[:orderitem][:quantity] == 0 + redirect_to action: :destroy + else + @orderitem.update(quantity: orderitem_params[:orderitem][:quantity]) + redirect_to cart_path + end + end + + def ship + @orderitem = Orderitem.find(params[:id]) + @orderitem.item_shipped + @orderitem.order.mark_shipped + redirect_to :back + end + + private + + def orderitem_params + params.permit(orderitem:[:quantity, :status]) + end + +end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb new file mode 100644 index 0000000000..3eb79af07b --- /dev/null +++ b/app/controllers/orders_controller.rb @@ -0,0 +1,93 @@ +class OrdersController < ApplicationController + #look up callbacks + #also, in order to make filter work, buttons to do stuff to orders need to send an id into params. (see guest_authorize method, which uses id) + #this is to help make it so only the person who started an order can do stuff to it. + before_action :guest_authorize, :only =>[:clear_cart, :cancel_as_guest, :pay] + before_action :navbar_categories, only: [:cart] + + + #the order from the perspective of the merchant + def show + @order = Order.find(params[:id]) + end + + #the order from the perspective of the guest + #stuff needed to view the cart page + def cart + if !session[:order_id] + @cart_status = "empty" + end + end + + #before you pay, clearing cart destroys order and orderitems. + #after you've paid, you instead cancel the order, and the order sticks around in the database + def clear_cart + @order = Order.find(session[:order_id]) + @order.destroy! + session[:order_id] = nil + redirect_to root_path + end + + def checkout + @order = Order.find(session[:order_id]) + end + + def confirm + @order = Order.find(session[:order_id]) + end + + def cancel_as_guest + @order = Order.find(session[:order_id]) + @order.update_attribute(:status, "cancelled") + session[:order_id] = nil + @cart_status = "empty" + redirect_to root_path + end + + def finalize + @order = Order.find(session[:order_id]) + @order.decrement_products_stock + session[:order_id] = nil + @cart_status = "empty" + flash[:notice] = "Thank you for your order!" + redirect_to root_path + end + + def pay + @order = Order.find(session[:order_id]) + @order.update(order_params[:order]) + @order.placed_at = Time.now + @order.status = "paid" + @order.save! + redirect_to order_confirm_path(@order.id) + end + + + #edit and update... are for the guest to do on the cart page? + #needs more thought + #we have lots of specific ways we are updating, as it stands right now + def edit + @order = Order.find(params[:id]) + end + + def update + id = params[:id] + order = Order.find(id) + order.update_attributes(order_params[:order]) + redirect_to order_path(params[:id]) + end + + private + + def order_params + params.permit(order:[:status, :cc_name, :email_address, :mailing_address, :cc_number, :cc_exp, :cc_cvv, :zip, :placed_at]) + end + + #views will need to make sure they send in an id to use here + def guest_authorize + unless session[:order_id] + redirect_to root_path + end + end + +end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb new file mode 100644 index 0000000000..5980897899 --- /dev/null +++ b/app/controllers/products_controller.rb @@ -0,0 +1,122 @@ + + +class ProductsController < ApplicationController + include ApplicationHelper + before_action :navbar_categories, only: [:index] + before_action :current_user_owns_product, only: [:update, :delete, :retire] + before_action :find_product, only: [:retire, :buy, :show, :destroy] + + + + def buy + #if there is not yet an order_id in session, make it now + #this is totally independent of being logged in. + #then if the id is nil, make an order and put it's id in the session hash + #if there already is an order in the session, add the product to it. + @current_order = current_order + if !@current_order + session[:order_id] = [] + order = Order.pending(@product) + session[:order_id] = order.id + flash[:notice] = "Added #{@product.name} to cart." + else + #logic for whether or not one is in cart already + if @current_order.orderitems.where(product_id: @product.id) != [] + #product is already in order + @orderitem = @current_order.orderitems.where(product_id: @product.id).first + @orderitem.update_attribute(:quantity, @orderitem.quantity + 1 ) + flash[:notice] = "Added another #{@orderitem.product.name} to cart." + else + #product is not already in order + @orderitem = Orderitem.create!(quantity: 1, order_id: @current_order.id, product_id: @product.id) + flash[:notice] = "Added #{@orderitem.product.name} to cart." + end + end + #in any case, want to stay on same page after clicking button + redirect_to request.referrer + end + + + def index + @products = Product.all + end + + def new + @product = Product.new + # @categories = @product.categories + @action = "create" + @all_categories = Category.all + end + + def create + @product = Product.new(product_params) + @product.price = (params[:product][:price].to_f * 100).to_i + if @product.save + redirect_to product_path(@product) + else + flash[:error] = "Why don't you double check those product specs, eh?" + render :new + end + end + + def show + @title = "#{@product.name} Info" + @stars = @product.avg_rating + @reviews = @product.reviews + @review = Review.new + end + + def review + @product = Product.find(params[:product_id]) + @review = Review.create(review_params) + redirect_to product_path(@product) + end + + def edit + id = params[:id] + @product = Product.find(id) + @categories = @product.categories + @all_categories = Category.all + @action = "update" + @title = "Edit #{@product.name}" + end + + def update + @product = Product.update(params[:id], product_params) + # @product.price = (params[:product][:price].to_f * 100).to_i + @product.category_ids = params[:product][:category_ids] + if @product.save + redirect_to product_path(@product) + else + render :edit + end + end + + def retire + id = params[:id] + @product = Product.find(id) + @product.retire_toggle + @product.save + redirect_to request.referrer + end + + def destroy + @product.destroy + flash[:notice] = "You've deleted #{@product.name}" + redirect_to request.referrer + end + + private + + def find_product + @product = Product.find(params[:id]) + end + + def product_params + params.require(:product).permit(:user_id, :retired, :category_ids, :name, :price, :description, :photo_url, :stock) + end + + def review_params + params.require(:review).permit(:rating, :body).merge(product_id: params[:product_id]) + end +end diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb new file mode 100644 index 0000000000..b3d77cc1c3 --- /dev/null +++ b/app/controllers/reviews_controller.rb @@ -0,0 +1,2 @@ +class ReviewsController < ApplicationController +end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb new file mode 100644 index 0000000000..0966e6540f --- /dev/null +++ b/app/controllers/sessions_controller.rb @@ -0,0 +1,42 @@ +class SessionsController < ApplicationController + def new + end + + def create + data = params[:session_data] + @user = User.find_by_email_address(data[:email_address]) + + if !@user.nil? + if @user.authenticate(data[:password]) + session[:user_id] = @user.id + flash[:notice] = "Welcome, #{@user.username}!" + redirect_to root_path + else + flash.now[:error] = "Your email was not found or password did not match. Please try again." + render :new + end + else + flash.now[:error] = "Your email was not found or password did not match. Please try again or sign up to create a new user." + render :new + end + end + + def destroy + session[:user_id] = nil if session[:user_id] + current_order + if !!@current_order + @current_order = Order.find(session[:order_id]) + @current_order.destroy! #destroys whatever order is in the session so long as it was only pending, which is done in an order validation + session[:order_id] = nil + end + flash[:notice] = "You have been logged out." + redirect_to root_path + end + + private + + def session_params + params.require(:user).permit(:username, :email_address, :password, :password_confirmation) + end + +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb new file mode 100644 index 0000000000..de56fdc06c --- /dev/null +++ b/app/controllers/users_controller.rb @@ -0,0 +1,52 @@ +class UsersController < ApplicationController +before_action :navbar_categories, only: [:index] +before_action :find_user, only: [:show, :dash, :product_dash, :order_dash] +before_action :only_current_user, only: [:dash, :order_dash] + + def index + @users = User.all + @cat = Category.all + end + + def new + @user = User.new + end + + def create + @user = User.new(strong_params) + if @user.save + session[:user_id] = @user.id + flash[:notice] = "Welcome to Quartzy! You are now logged in." + redirect_to root_path + else + render :new + end + end + + def show + end + + def dash + end + + def product_dash + end + + def order_dash + @user = @current_user + session[:rev_status] = params[:rev_status] if !params[:rev_status].nil? + session[:order_status] = params[:order_status] if !params[:order_status].nil? + session[:order_status] = 'all' if session[:order_status].nil? + end + + private + + def strong_params + params.require(:user).permit(:username, :email_address, :password, :password_confirmation) + end + + def find_user + @user = User.find(params[:id]) + end + +end diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb new file mode 100644 index 0000000000..40c6fa319e --- /dev/null +++ b/app/controllers/welcome_controller.rb @@ -0,0 +1,24 @@ +class WelcomeController < ApplicationController + before_action :navbar_categories, only: [:index] + + def index + x = rand(1..User.all.length) + until User.find(x).products.length >= 2 + x = rand(1..User.all.length) + end + y = rand(1..User.all.length) + until y != x && User.find(y).products.length >= 2 + y = rand(1..User.all.length) + end + @top_users = [User.find(x), User.find(y)] + m = rand(1..Category.all.length) + until Category.find(m).products.length >= 2 + m = rand(1..Category.all.length) + end + n = rand(1..Category.all.length) + until n != m && Category.find(n).products.length >= 2 + n = rand(1..Category.all.length) + end + @top_categories = [Category.find(m), Category.find(n)] + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index de6be7945c..95fdc53368 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,2 +1,9 @@ +require "action_view/helpers/number_helper" + module ApplicationHelper + include ActionView::Helpers::NumberHelper + def nice_price(price) + price = price / 100.0 + number_to_currency(price) + end end diff --git a/app/helpers/categories_helper.rb b/app/helpers/categories_helper.rb new file mode 100644 index 0000000000..e06f31554c --- /dev/null +++ b/app/helpers/categories_helper.rb @@ -0,0 +1,2 @@ +module CategoriesHelper +end diff --git a/app/helpers/categoryproducts_helper.rb b/app/helpers/categoryproducts_helper.rb new file mode 100644 index 0000000000..c7e72f5504 --- /dev/null +++ b/app/helpers/categoryproducts_helper.rb @@ -0,0 +1,2 @@ +module CategoryproductsHelper +end diff --git a/app/helpers/orderitems_helper.rb b/app/helpers/orderitems_helper.rb new file mode 100644 index 0000000000..c74e407d1c --- /dev/null +++ b/app/helpers/orderitems_helper.rb @@ -0,0 +1,2 @@ +module OrderitemsHelper +end diff --git a/app/helpers/orders_helper.rb b/app/helpers/orders_helper.rb new file mode 100644 index 0000000000..443227fd48 --- /dev/null +++ b/app/helpers/orders_helper.rb @@ -0,0 +1,2 @@ +module OrdersHelper +end diff --git a/app/helpers/products_helper.rb b/app/helpers/products_helper.rb new file mode 100644 index 0000000000..ab5c42b325 --- /dev/null +++ b/app/helpers/products_helper.rb @@ -0,0 +1,2 @@ +module ProductsHelper +end diff --git a/app/helpers/reviews_helper.rb b/app/helpers/reviews_helper.rb new file mode 100644 index 0000000000..682b7b1abc --- /dev/null +++ b/app/helpers/reviews_helper.rb @@ -0,0 +1,2 @@ +module ReviewsHelper +end diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb new file mode 100644 index 0000000000..309f8b2eb3 --- /dev/null +++ b/app/helpers/sessions_helper.rb @@ -0,0 +1,2 @@ +module SessionsHelper +end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb new file mode 100644 index 0000000000..2310a240d7 --- /dev/null +++ b/app/helpers/users_helper.rb @@ -0,0 +1,2 @@ +module UsersHelper +end diff --git a/app/helpers/welcome_helper.rb b/app/helpers/welcome_helper.rb new file mode 100644 index 0000000000..eeead45fc9 --- /dev/null +++ b/app/helpers/welcome_helper.rb @@ -0,0 +1,2 @@ +module WelcomeHelper +end diff --git a/app/models/categories_product.rb b/app/models/categories_product.rb new file mode 100644 index 0000000000..6f63ba6762 --- /dev/null +++ b/app/models/categories_product.rb @@ -0,0 +1,4 @@ +class CategoriesProduct < ActiveRecord::Base + belongs_to :category + belongs_to :product +end diff --git a/app/models/category.rb b/app/models/category.rb new file mode 100644 index 0000000000..d5e497e0e3 --- /dev/null +++ b/app/models/category.rb @@ -0,0 +1,14 @@ +class Category < ActiveRecord::Base + has_many :categories_products, :dependent => :destroy + has_many :products, through: :categories_products + belongs_to :user + + validates :name, presence: true + validates :name, uniqueness: true + + def top(x) + products = self.products.where(retired: false).sort_by{|pro| pro.avg_rating} + return products[0..x-1] + end + +end diff --git a/app/models/order.rb b/app/models/order.rb new file mode 100644 index 0000000000..2c91fd1ee5 --- /dev/null +++ b/app/models/order.rb @@ -0,0 +1,77 @@ +class Order < ActiveRecord::Base + belongs_to :user + has_many :orderitems, :dependent => :destroy + has_many :products, through: :orderitems + + validate :has_orderitem, on: :create + validate :customer_destroys_only_pending, on: :destroy + validates :status, presence: true + validates :status, inclusion: { in: %w(pending) }, on: :create + validates :status, inclusion: { in: %w(paid) }, on: :pay + validates :status, inclusion: { in: %w(complete) }, on: :ship + validates :status, inclusion: { in: %w(cancelled) }, on: :cancel + validates :cc_name, presence: true, on: :pay + validates :email_address, presence: true, on: :pay + validates :mailing_address, presence: true, on: :pay + validates :cc_number, presence: true, on: :pay + validates :zip, presence: true, on: :pay + validates :cc_exp, presence: true, on: :pay + validates :cc_cvv, presence: true, on: :pay + + def self.pending(first_product) + Order.transaction do + order = Order.new(status: 'pending') + order.orderitems << Orderitem.create!(quantity: 1, order_id: order.id, product_id: first_product.id) + order.save! + return order + end + end + + def decrement_products_stock + Order.transaction do + self.orderitems.each do |orderitem| + product = orderitem.product + product.stock -= orderitem.quantity + product.save! + end + end + end + + def total + sales = [] + self.orderitems.each do |orderitem| + sales.push(orderitem.quantity * orderitem.product.price) + end + return sales.inject(0) {|r, e| r + e } + end + + def total_by_user(user_id) + sales = [] + self.products.each do |product| + sales.push(product.price) if product.user_id == user_id + end + return sales.inject(0) {|r, e| r + e } + end + + def mark_shipped + c = 0 + self.orderitems.each do |orderitem| + c += 1 if orderitem.status == 'shipped' + end + self.status = 'completed' if c == self.orderitems.length + self.save + return self + end + #returns the last four numbers of the cc + def last_four + return self.cc_number[-4..-1] + end + + def customer_destroys_only_pending + !session[:user_id] && self.status = "pending" + end + + def has_orderitem + !!self.orderitems + end +end diff --git a/app/models/orderitem.rb b/app/models/orderitem.rb new file mode 100644 index 0000000000..fb0e237a91 --- /dev/null +++ b/app/models/orderitem.rb @@ -0,0 +1,14 @@ +class Orderitem < ActiveRecord::Base + belongs_to :order + belongs_to :product + validates :quantity, presence: true + + + + # decerements inventory of product + def item_shipped + self.status = 'shipped' + self.save + end + +end diff --git a/app/models/product.rb b/app/models/product.rb new file mode 100644 index 0000000000..15f9d94516 --- /dev/null +++ b/app/models/product.rb @@ -0,0 +1,59 @@ +class Product < ActiveRecord::Base + belongs_to :user + has_many :reviews, :dependent => :destroy + has_many :orderitems + has_many :orders, through: :orderitems + has_many :categories_products #, :dependent => :destroy + has_many :categories, through: :categories_products + + validates :name, presence: true + validates :name, uniqueness: true + validates :price, presence: true + validates_numericality_of :price, :greater_than => 0 + validates_numericality_of :stock, :greater_than_or_equal_to => 0 + # validates :retired, inclusion: { in: %w(false) }, on: :create + validate :belongs_to_user? + + # Takes an array of products and returns the x number of products in order of which sold the most often + def self.top_selling(product_array, x) + sales_hash = {} + product_array.each do |product| + revenue = product.orderitems.length * product.price + sales_hash[product] = revenue + end + top = sales_hash.sort_by{|k, v| v} + top_array = top[0..x-1].flatten.reject!{|item| item.class == Fixnum} + return top_array + end + + # returns the average rating for all ratings for a given product + def avg_rating + total = 0 + self.reviews.each do |r| + total += r.rating + end + if self.reviews.length > 0 + avg = total / self.reviews.length + else + avg = 0 + end + return avg + end + + def belongs_to_user? + !!self.user + end + + def out_of_stock? + self.stock == 0 + end + + def retire_toggle + if self.retired + self.retired = false + elsif !self.retired + self.retired = true + end + end + +end diff --git a/app/models/review.rb b/app/models/review.rb new file mode 100644 index 0000000000..6eb6e4c822 --- /dev/null +++ b/app/models/review.rb @@ -0,0 +1,7 @@ +class Review < ActiveRecord::Base + belongs_to :product + + validates :rating, presence: true + validates :rating, numericality: { only_integer: true } + validates :rating, :inclusion => 1..5 +end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000000..bcd4e7a465 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,87 @@ +class User < ActiveRecord::Base + has_many :products, :dependent => :destroy + has_many :categories + + validates :username, presence: true + validates :username, uniqueness: true + + validates :email_address, presence: true + validates :email_address, uniqueness: true + + validates_confirmation_of :password, :message => "Passwords should match" + has_secure_password + + # returns the top x number of products the user sells based on their average rating + def top(x) + products = self.products.where(retired: false).sort_by{|pro| pro.avg_rating} + return products[0..x-1] + end + + # returns all the orders that have any products in them belonging to the user + def orders + orders = [] + self.products.each do |product| + product.orders.each do |order| + orders.push(order) if !orders.include?(order) + end + end + return orders + end + + def orderitems + orderitems = [] + self.products.each do |product| + product.orderitems.each do |oi| + orderitems.push(oi) + end + end + return orderitems + end + + # returns orderitems for the user that are in a given order + def orderitems_by_order(order) + orderitems = [] + self.products.each do |product| + product.orderitems.each do |oi| + orderitems.push(oi) if oi.order == order + end + end + return orderitems + end + + # returns all the orders a user is associated with, based on the order status + def orders_by_status(status) + orders = [] + self.products.each do |product| + product.orders.each do |order| + orders.push(order) if order.status == "#{status}" + end + end + return orders + end + + # returns total revenue for a user + def revenue + rev = [] + self.products.each do |product| + product.orderitems.each do |orderitem| + rev.push(orderitem.product.price * orderitem.quantity) + end + end + total = rev.inject(0) {|r, e| r + e} + return total + end + + # returns revenue for user by order status + def rev_by_status(status) + rev = [] + self.products.each do |product| + product.orderitems.each do |orderitem| + rev.push(orderitem.product.price * orderitem.quantity) if orderitem.order.status == "#{status}" + end + end + total = rev.inject{|r, e| r + e} + return total + end + +end diff --git a/app/views/application/_cat_navbar.html.erb b/app/views/application/_cat_navbar.html.erb new file mode 100644 index 0000000000..5425badf37 --- /dev/null +++ b/app/views/application/_cat_navbar.html.erb @@ -0,0 +1,5 @@ + diff --git a/app/views/application/_navbar.html.erb b/app/views/application/_navbar.html.erb new file mode 100644 index 0000000000..2fbee45049 --- /dev/null +++ b/app/views/application/_navbar.html.erb @@ -0,0 +1,14 @@ + diff --git a/app/views/application/_product_view.html.erb b/app/views/application/_product_view.html.erb new file mode 100644 index 0000000000..9d6a5fb6d6 --- /dev/null +++ b/app/views/application/_product_view.html.erb @@ -0,0 +1,25 @@ +<% collection.to_ary.in_groups_of(3, false) do |group| %> +
+ <% group.each do |p| %> +
+
+ <%= image_tag "#{p.photo_url}", class: "img-responsive, product-page-img" %> +
+

+ <%= link_to "#{p.name}", product_path(p) %> +

+
+ <% if @current_user != nil %> + <% if p.user_id != @current_user.id && !p.out_of_stock? %> + <%= button_to "Add to Cart", buy_path(p.id), class: "btn btn-success" %> + <% end %> + <% elsif @current_user.nil? && !p.out_of_stock? %> + <%= button_to "Add to Cart", buy_path(p.id), class: "btn btn-success" %> + <% else %> + OUT OF STOCK + <% end %> +
+
+ <% end %> +
+<% end %> diff --git a/app/views/categories/_form.html.erb b/app/views/categories/_form.html.erb new file mode 100644 index 0000000000..3ddc1528bb --- /dev/null +++ b/app/views/categories/_form.html.erb @@ -0,0 +1,19 @@ +<%= form_for @category, url: {action: @action }, :html => { :class => "form" } do |f| %> +
+
+ <%= f.label :name %> + <%= f.text_field :name, class: "form-control" %> +
+ +
+ <%= f.label :description %> + <%= f.text_field :description, class: "form-control" %> +
+ +
+ <%= f.hidden_field :user_id, :value => session[:user_id] %> +
+ +
+ <%= f.submit class: "btn btn-info" %> +<% end %> diff --git a/app/views/categories/edit.html.erb b/app/views/categories/edit.html.erb new file mode 100644 index 0000000000..e0f80e7747 --- /dev/null +++ b/app/views/categories/edit.html.erb @@ -0,0 +1 @@ +<%= render "form" %> diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb new file mode 100644 index 0000000000..e9858a131a --- /dev/null +++ b/app/views/categories/index.html.erb @@ -0,0 +1,39 @@ +<%= render 'cat_navbar' %> +
+

+ Products by Category +

+
+ + <% @cat.to_ary.in_groups_of(3, false) do |group| %> +
+ <% group.each do |cat| %> +
+
+

+ <%= link_to "#{cat.name}", category_path(cat), class: 'category-box' %> +

+ <% cat.top(3).each do |p| %> +
+ <%= image_tag "#{p.photo_url}", class: "img-responsive, product-page-img" %> +
+

+ <%= link_to "#{p.name}", product_path(p) %> +

+
+ <% if @current_user != nil %> + <% if p.user_id != @current_user.id && !p.out_of_stock? %> + <%= button_to "Add to Cart", buy_path(p.id), class: "btn btn-success" %> + <% end %> + <% elsif @current_user.nil? && !p.out_of_stock? %> + <%= button_to "Add to Cart", buy_path(p.id), class: "btn btn-success" %> + <% elsif p.out_of_stock? %> + <%= button_to "OUT OF STOCK" %> + <% end %> +
+ <% end %> +
+
+ <% end %> +
+ <% end %> diff --git a/app/views/categories/new.html.erb b/app/views/categories/new.html.erb new file mode 100644 index 0000000000..e0f80e7747 --- /dev/null +++ b/app/views/categories/new.html.erb @@ -0,0 +1 @@ +<%= render "form" %> diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb new file mode 100644 index 0000000000..69efcb5b9d --- /dev/null +++ b/app/views/categories/show.html.erb @@ -0,0 +1,7 @@ +<%= render 'cat_navbar' %> + +
+

<%= "#{@category.name}" %>

+
+ +<%= render partial: 'product_view', locals: {collection: @category.products.where(retired: false)} %> \ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 9b70e01c2e..3693980dd3 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,14 +1,24 @@ - Betsy + Gems on Gems on Gems <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> <%= csrf_meta_tags %> + + + - -<%= yield %> - +
+ <% if !flash.empty? %> +
+ <% flash.each do |key, value| %><%= value %> + <% end %> +
+ <% end %> + <%= render 'navbar' %> + <%= yield %> +
diff --git a/app/views/orders/cart.html.erb b/app/views/orders/cart.html.erb new file mode 100644 index 0000000000..b70ddf2c7a --- /dev/null +++ b/app/views/orders/cart.html.erb @@ -0,0 +1,86 @@ +
+

+ Your Cart +

+
+
+
+ <% if @current_order == nil %> +

Your cart is empty

+

<%= link_to "Go shopping!", products_path %>

+ <% else %> +
+
+
+
+
+ + + + + + + + <% @current_order.orderitems.each do |orderitem| %> + + + + + + + + + + + + + + + + + + <% end %> +
ProductDescriptionTotalPhoto
+ <%= link_to "#{orderitem.product.name}", product_path(orderitem.product) %> + + <%= orderitem.product.description%> + + <%= nice_price(orderitem.product.price * orderitem.quantity) %> + + <%= image_tag orderitem.product.photo_url, class: "img-responsive cart-img" %> +
+ Category + + <% orderitem.product.categories.each do |category| %> + <%= category.name %> + <% end %> +
+ Quantity + + <%= form_for orderitem, url: orderitems_update_path(orderitem.id), method: :patch do |f| %> + <%= f.number_field :quantity, min: 1 %> + <%= f.submit "Change", class: "btn btn-default" %> + <% end %> +
+ <%= button_to "Remove from Cart", orderitems_delete_path(orderitem.id), method: :delete, class: "btn btn-danger" %> +
+
+
+
+
+
+
+
+ <%= button_to "Checkout", checkout_path, method: :get, class: "btn btn-success" %> +
+
+ <%= button_to "Empty Cart", clear_cart_path, method: :delete, class: "btn btn-danger" %> +
+
+
+
+
+ + + +<% end %> diff --git a/app/views/orders/checkout.html.erb b/app/views/orders/checkout.html.erb new file mode 100644 index 0000000000..88a075af71 --- /dev/null +++ b/app/views/orders/checkout.html.erb @@ -0,0 +1,138 @@ +
+

+ Enter Payment Info +

+
+
+ +
+
+
+ <%= form_for @order, url: {controller: "orders", action: "pay" }, :html => { :class => "form" } do |f| %> +
+
+ <%= f.label :cc_name, "Name on Credit Card" %> + <%= f.text_field :cc_name, class: "form-control", :required => true %> +
+ +
+ <%= f.label :email_address, "Email" %> + <%= f.email_field :email_address, class: "form-control", :required => true %> +
+ +
+ <%= f.label :mailing_address, "Mailing Address" %> + <%= f.text_field :mailing_address, class: "form-control", :required => true %> +
+ +
+ <%= f.label :cc_number, "Credit Card Number" %> + <%= f.text_field :cc_cvv, class: "form-control", :required => true %> +
+ +
+ <%= f.label :cc_exp, "Credit Card Expiration" %> + <%= f.text_field :cc_exp, class: "form-control", :required => true %> +
+ +
+ <%= f.label :cc_cvv, "Credit Card CVV" %> + <%= f.text_field :cc_cvv, class: "form-control", :required => true %> +
+ +
+ <%= f.label :zip, "Zip Code" %> + <%= f.text_field :zip, class: "form-control", :required => true %> +
+ + <%= f.submit "Purchase", :class => 'btn btn-success' %> + <% end %> +
+
+
+ +
+

+ Review Your Order +

+
+
+
+
+ + <% @order.orderitems.each do |orderitem| %> + + + + + + + + + + + + + + + + + + + + + + + + + + + + <% end %> +
+ Product + + <%= orderitem.product.name %> +
+ Description + + <%= orderitem.product.description%> +
+ Price + + <%= nice_price(orderitem.product.price) %> +
+ Photo + + <%= image_tag orderitem.product.photo_url %> +
+ Category + + <% orderitem.product.categories.each do |category| %> + <%= category.name %> + <% end %> +
+ Quantity + + <%= orderitem.quantity %> +
+ <%= button_to "Remove from Cart", orderitems_delete_path(orderitem.id), method: :delete, class:'btn btn-danger' %> +
+
+
+
+
+
+
+

+ <%= button_to "Cancel Order", clear_cart_path, method: :delete, class:'btn btn-danger cntr-header' %> +

+
+
+
diff --git a/app/views/orders/confirm.html.erb b/app/views/orders/confirm.html.erb new file mode 100644 index 0000000000..cd48f98545 --- /dev/null +++ b/app/views/orders/confirm.html.erb @@ -0,0 +1,60 @@ +
+

+ Order #<%= @order.id %> Confirmation +

+
+ + +
+
+ Name: <%= @order.cc_name %>
+ E-mail: <%= @order.email_address %>
+ Mailing Address: <%= @order.mailing_address %>
+ Order Placed: <%= @order.placed_at.strftime("%B %d, %Y") %>
+ Order Status: <%= @order.status.capitalize %>
+ <%= %>
+
+
+ +
+
+ + + + + + + <% @order.orderitems.each do |orderitem| %> + + + + + + <% end %> + + + + + +
ProductQuantityPrice
+ <%= link_to "#{orderitem.product.name}", product_path(orderitem.product) %> + + <%= orderitem.quantity %> + + <%= nice_price(orderitem.product.price * orderitem.quantity) %> +
Total: <%= nice_price(@order.total) %>
+
+ +
+ +
+
+
+
+ <%= button_to "Finalize Order", {action: :finalize, controller: :orders}, method: :patch, class: "btn btn-success" %> +
+
+ <%= button_to "Cancel Order", {action: :cancel_as_guest, controller: :orders}, method: :patch, class: "btn btn-danger" %> +
+
+
diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb new file mode 100644 index 0000000000..554d389e85 --- /dev/null +++ b/app/views/orders/show.html.erb @@ -0,0 +1,44 @@ +
+

Order <%= @order.id %>

+
Order status: <%= @order.status.capitalize %>
+
+
+
+

+ Customer Information +

+ Name: <%= @order.cc_name %>
+ Email: <%= @order.email_address %>
+ Mailing Address: <%= @order.mailing_address %>
+ Zip: <%= @order.zip %>
+ Last Four Digits of CC: <%= @order.last_four %>
+ Status: <%= @order.status.capitalize %>
+ Placed at: <%= @order.placed_at.strftime("%B %d, %Y") %>
+
+

+
+

+ My Products in Order +

+ + + + + + + + <% @current_user.orderitems_by_order(@order).each do |orderitem| %> + + + + + <% if orderitem.status != 'shipped' %> + + <% else %> + + <% end %> + + <% end %> +
ProductQuantityTotalShipped?
<%= link_to "#{orderitem.product.name}", product_path(orderitem.product) %><%= orderitem.quantity %><%= nice_price(orderitem.product.price * orderitem.quantity) %><%= link_to "Mark Shipped", ship_path(orderitem) %><%= orderitem.status.capitalize %>
+
+
diff --git a/app/views/products/_form.html.erb b/app/views/products/_form.html.erb new file mode 100644 index 0000000000..297c023b62 --- /dev/null +++ b/app/views/products/_form.html.erb @@ -0,0 +1,54 @@ + + + +<%= form_for @product, url: {action: @action}, :html => { :class => "form" } do |f| %> +
+
+ <%= f.label :name %> + <%= f.text_field :name, class: "form-control", :required => true %> +
+ +
+ <%= f.label :description %> + <%= f.text_field :description, class: "form-control" %> +
+ +
+ <%= f.label :price %> + <%= f.text_field :price, class: "form-control", :required => true %> +
+ +
+ <%= f.label :photo_url %> + <%= f.url_field :photo_url, class: "form-control" %> +
+ +
+ <%= f.label :stock %> + <%= f.number_field :stock, class: "form-control", :required => true %> +
+ +
+ <%= f.label :category, "Categories" %>
+ <%= f.collection_check_boxes :category_ids, Category.all, :id, :name do |b| %> + <%= b.check_box %> + <%= b.label %>
+ <% end %> +
+ +
+ <%= f.label :retired, "Check to retire this product" %>
+ <%= f.check_box :retired %> + <%= f.label :retired, "Retired" %> +
+ + <%= f.hidden_field :user_id, :value => session[:user_id] %> +
+ <%= f.submit class: "btn btn-info" %> +<% end %> diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb new file mode 100644 index 0000000000..e0f80e7747 --- /dev/null +++ b/app/views/products/edit.html.erb @@ -0,0 +1 @@ +<%= render "form" %> diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb new file mode 100644 index 0000000000..a905142607 --- /dev/null +++ b/app/views/products/index.html.erb @@ -0,0 +1,5 @@ +<%= render 'cat_navbar' %> + +

All Products

+ +<%= render partial: 'product_view', locals: {collection: @products.where(retired: false)} %> diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb new file mode 100644 index 0000000000..e0f80e7747 --- /dev/null +++ b/app/views/products/new.html.erb @@ -0,0 +1 @@ +<%= render "form" %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb new file mode 100644 index 0000000000..bf035431f0 --- /dev/null +++ b/app/views/products/show.html.erb @@ -0,0 +1,184 @@ +
+

+ <%= @title %> +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <% if @current_user != nil %> + <% if @product.user_id == @current_user.id %> + + + + + <% end %> +
+ Product + + <%= @product.name %> +
+ Sold By: + + <%= link_to @product.user.username, user_path(@product.user_id)%> +
+ Description + + <%= @product.description%> +
+ Price + + <%= nice_price(@product.price) %> +
+ Photo + + <%= image_tag @product.photo_url, class: 'img-responsive product-page-img' %> +
+ Stock + + <%= @product.stock%> +
+ Category + + <% @product.categories.each do |category| %> +
    +
  • <%= category.name %>
  • +
+ <% end %> +
+ Average Rating + + <% if @stars == 5 %> + <% 5.times do %> + + <% end %> + <% else %> + <% @stars.times do %> + + <% end %> + <% (5 - @stars).times do %> + + <% end %> + <% end %> +
+ Reviews + + <% @product.reviews.each do |rev| %> + <% if rev.rating == 5 %> + <% rev.rating.times do %> + + <% end %> + <% else %> + <% rev.rating.times do %> + + <% end %> + <% (5 - rev.rating).times do %> + + <% end %> + <% end %> +

<%= rev.body %>

+ <% end %> +
+ Retired? + + <% if @product.retired == false %> + No + <% else %> + Yes + <% end %> + <% end %> +
+
+
+ + +<% if @current_user == nil || @product.user_id != @current_user.id %> + <%= form_for @review, url: product_review_path(@product), :html => { :class => "sub-form" } do |f| %> +
+
+ <%= f.label :rating, "Rate It:" %> + <%= f.select :rating, [1, 2, 3, 4, 5], class: "form-control" %>
+ <%= f.label :body, "Tell us why" %>: + <%= f.text_area :body, class: "form-control" %> + <%= f.submit class: "btn btn-default rating-btn" %> +
+
+ <% end %> +<% end %> +

+ +
+ <% if @current_user != nil %> + <% if @product.user_id != @current_user.id %> +
+ <% if !@product.out_of_stock? %> + <%= button_to "Add to Cart", buy_path(@product.id), class: "btn btn-success" %> + <% else %> + OUT OF STOCK + <% end %> +
+
+ <%= button_to "All Products", products_path, method: :get, class: "btn btn-default" %> +
+ <% else %> +
+ <%= button_to "Edit", edit_product_path(@product), method: :get, class: "btn btn-default" %> +
+
+ <%= button_to "Delete", product_path(@product.id), method: :delete, class: "btn btn-danger" %> +
+
+ <%= button_to "All Products", products_path, method: :get, class: "btn btn-default" %> +
+ <% end %> + <% else %> +
+ <% if !@product.out_of_stock? %> + <%= button_to "Add to Cart", buy_path(@product.id), class: "btn btn-success" %> + <% else %> + OUT OF STOCK + <% end %> +
+
+ <%= button_to "All Products", products_path, method: :get, class: "btn btn-default" %> +
+ <% end %> +
+
diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb new file mode 100644 index 0000000000..36aa4fe65c --- /dev/null +++ b/app/views/sessions/new.html.erb @@ -0,0 +1,19 @@ + +
+
+

+ Login +

+ <%= form_for(:session_data, url: sessions_path) do |f| %> +
+ <%= f.label :email_address %>: + <%= f.email_field :email_address, class: "form-control", :required => true %> + + <%= f.label :password %>: + <%= f.password_field :password, class: "form-control", :required => true %>
+ + <%= f.submit "Login", class: "btn btn-default" %> + <% end %> +
+
+
diff --git a/app/views/users/dash.html.erb b/app/views/users/dash.html.erb new file mode 100644 index 0000000000..97be2e0f5b --- /dev/null +++ b/app/views/users/dash.html.erb @@ -0,0 +1,47 @@ +

+ Hello, <%= @user.username %> +

+ + +
+
+ <% if @user.products.length != 0 %> +

+ <%= link_to 'Top Selling Products', user_products_dash_path(@user) %> +

+
    + <% Product.top_selling(@user.products, 3).each do |product| %> +

    +
  • + <%= link_to "#{product.name}", product_path(product) %> +
  • +

    + <% end %> +
+ <% else %> +

+ You don't have any products yet. +

+ <% end %> +
+
+ <% if @user.orders.length != 0 %> +

+ <%= link_to 'Recent Orders', user_order_dash_path(@user) %> +

+
    + <% @user.orders.sort_by{|order| order.created_at}.first(3).each do |order| %> +
  • +

    + <%= link_to "Order #{order.id}", order_path(order.id) %> +

    +
  • + <% end %> +
+ <% else %> +

+ You don't have any orders yet. +

+ <% end %> +
+
diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb new file mode 100644 index 0000000000..b274188628 --- /dev/null +++ b/app/views/users/index.html.erb @@ -0,0 +1,39 @@ +<%= render 'cat_navbar' %> +
+

+ Products by Merchant +

+
+ +<% @users.to_ary.in_groups_of(3, false) do |group| %> +
+ <% group.each do |user| %> +
+
+

+ <%= link_to "#{user.username}", user_path(user), class: 'category-box' %> +

+ <% user.top(2).each do |p| %> +
+ <%= image_tag "#{p.photo_url}", class: "img-responsive, product-page-img" %> +
+

+ <%= link_to "#{p.name}", product_path(p), class:"product-names" %> +

+
+ <% if @current_user != nil %> + <% if p.user_id != @current_user.id && !p.out_of_stock? %> + <%= button_to "Add to Cart", buy_path(p.id), class: "btn btn-success" %> + <% end %> + <% elsif @current_user.nil? && !p.out_of_stock? %> + <%= button_to "Add to Cart", buy_path(p.id), class: "btn btn-success" %> + <% elsif p.out_of_stock? %> + <%= button_to "OUT OF STOCK" %> + <% end %> +
+ <% end %> +
+
+ <% end %> +
+<% end %> diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb new file mode 100644 index 0000000000..167724643e --- /dev/null +++ b/app/views/users/new.html.erb @@ -0,0 +1,23 @@ +
+

+ Sign Up +

+ <%= form_for @user do |f| %> +
+ <%= f.label :username %> + <%= f.text_field :username, class: "form-control" %>
+ + <%= f.label :email_address %> + <%= f.text_field :email_address, class: "form-control" %>
+ + <%= f.label :password %> + <%= f.password_field :password, class: "form-control" %>
+ + <%= f.label :password_confirmation %> + <%= f.password_field :password_confirmation, class: "form-control" %>
+ + <%= f.submit class: 'btn btn-default' %>
+ <% end %> +
+
+
diff --git a/app/views/users/order_dash.html.erb b/app/views/users/order_dash.html.erb new file mode 100644 index 0000000000..75a7f7189e --- /dev/null +++ b/app/views/users/order_dash.html.erb @@ -0,0 +1,89 @@ +
+

+ <%= @user.username %> +

+
+
+ <% if @user.revenue.nil? %> +

+ You haven't made any money yet! Get sellin'. +

+ <% elsif !@user.revenue.nil? %> +

+ Total Revenue: <%= nice_price(@user.revenue) %> +

+

+ order revenue by: + <%= link_to "pending", user_order_dash_path(@user, rev_status: "pending") %> / + <%= link_to "paid", user_order_dash_path(@user, rev_status: "paid") %> / + <%= link_to "completed", user_order_dash_path(@user, rev_status: "completed") %> / + <%= link_to "cancelled", user_order_dash_path(@user, rev_status: "cancelled") %> +

+ <% if !session[:rev_status].nil? %> +

+ <% if @user.rev_by_status(session[:rev_status]).nil? %> + You don't have any <%= session[:rev_status]%> orders. + <% else %> + Revenue for <%= session[:rev_status]%> orders is: <%= nice_price(@user.rev_by_status(session[:rev_status])) %> + <% end %> +

+ <% elsif session[:rev_status].nil? %> +

+ select a status for which you want to see total revenue +

+ <% end %> + <% end %> +
+
+

+ Total Orders: <%= @user.orders.length %> +

+

+ orders by status:
+

+

+ <%= link_to "all", user_order_dash_path(@user, order_status: "all") %> / + <%= link_to "pending", user_order_dash_path(@user, order_status: "pending") %> / + <%= link_to "paid", user_order_dash_path(@user, order_status: "paid") %> / + <%= link_to "completed", user_order_dash_path(@user, order_status: "completed") %> / + <%= link_to "cancelled", user_order_dash_path(@user, order_status: "cancelled") %> +

+
+
+ + + + + + + + + + + <% @user.orderitems.each do |orderitem| %> + <% if orderitem.order.status == session[:order_status] || session[:order_status] == 'all' %> + + + + <% if !orderitem.order.placed_at.nil? %> + + <% else %> + + <% end %> + + + + <% if orderitem.order.status == "paid" && orderitem.status != 'shipped' %> + + <% elsif orderitem.order.status == 'cancelled' %> + + <% elsif orderitem.order.status == 'pending' %> + + <% else %> + + <% end %> + + <% end %> + <% end %> +
Order #ProductOrder PlacedOrder StatusQuantityTotalMark Shipped
<%= link_to "#{orderitem.order.id}", order_path(orderitem.order) %><%= link_to "#{orderitem.product.name}", product_path(orderitem.product) %><%= orderitem.order.placed_at.strftime("%B %d, %Y") %>Order Pending<%= orderitem.order.status.capitalize %><%= orderitem.quantity %><%= nice_price(orderitem.product.price * orderitem.quantity) %><%= link_to "Mark Shipped", ship_path(orderitem), class: "mark_shipped", method: :patch %>Order Canceled :(Order Pending<%= orderitem.status.capitalize %>
+
diff --git a/app/views/users/product_dash.html.erb b/app/views/users/product_dash.html.erb new file mode 100644 index 0000000000..e42367cc9b --- /dev/null +++ b/app/views/users/product_dash.html.erb @@ -0,0 +1,30 @@ +

<%= @user.username %>

+

Active Products

+ + + <% @user.products.where(retired:false).each do |product| %> + + + + + + <% end %> +
<%= link_to "#{product.name}", product_path(product) %> In stock: <%= product.stock %> + <%= link_to "Edit", edit_product_path(product), method: :get, class: "btn btn-default" %> <%= link_to "Delete", product_path(product), method: :delete, class: "btn btn-danger" %> <%= link_to "Retire", retire_path(product), method: :patch, class: "btn btn-info" %>
+<%= link_to "Add a New Product", new_product_path, method: :get %>
+<%= link_to "Add a New Category", new_category_path, method: :get %> + + +

Inactive Products

+ + + + <% @user.products.where(retired:true).each do |product| %> + + + + + + <% end %> +

<%= link_to "#{product.name}", product_path(product) %>

In stock: <%= product.stock %> + <%= link_to "Edit", edit_product_path(product), method: :get, class: "btn btn-default" %><%= link_to "Delete", product_path(product), method: :delete, class: "btn btn-default" %> <%= link_to "Activate", retire_path(product), method: :patch, class: "btn btn-success" %>
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb new file mode 100644 index 0000000000..ee952529ff --- /dev/null +++ b/app/views/users/show.html.erb @@ -0,0 +1,5 @@ +
+

<%= @user.username %>

+
+ +<%= render partial: 'product_view', locals: {collection: @user.products.where(retired: false)} %> \ No newline at end of file diff --git a/app/views/welcome/index.html.erb b/app/views/welcome/index.html.erb new file mode 100644 index 0000000000..800b8d9cda --- /dev/null +++ b/app/views/welcome/index.html.erb @@ -0,0 +1,57 @@ +<%= render 'cat_navbar' %> + +
+

Welcome to Quartzy

+

(gems on gems on gems)

+
+
+ <%= link_to "All Dem Gemz", products_path, class: 'home-btn, btn btn-default' %> +
+
+
+
+
+

<%= link_to "Merchants", users_path, class: 'front-pg-link' %>

+ + <% @top_users.each do |user| %> +
+

+ <%= link_to "#{user.username}", user_path(user), class: 'category-box' %> +

+ + <% user.top(2).each do |product| %> +

+ <%= image_tag "#{product.photo_url}", class: "img-responsive, product-page-img" %>
+ <%= link_to "#{product.name}", product_path(product) %>
+

+ <% end %> +
+ <% end %> +
+
+

<%= link_to "Gem Categories", categories_path, class: 'front-pg-link' %>

+ <% @top_categories.each do |category| %> +
+

+ <%= link_to "#{category.name}", category_path(category), class: 'category-box' %> +

+ <% category.top(2).each do |product| %> +

+ <%= image_tag "#{product.photo_url}", class: "img-responsive, product-page-img" %>
+ <%= link_to "#{product.name}", product_path(product) %>
+

+ <% end %> +
+ <% end %> +
+
+ +

+ diff --git a/config/routes.rb b/config/routes.rb index 3f66539d54..53d748c78e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,56 +1,46 @@ Rails.application.routes.draw do - # The priority is based upon order of creation: first created -> highest priority. - # See how all your routes lay out with "rake routes". - - # You can have the root of your site routed with "root" - # root 'welcome#index' - - # Example of regular route: - # get 'products/:id' => 'catalog#view' - - # Example of named route that can be invoked with purchase_url(id: product.id) - # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase - - # Example resource route (maps HTTP verbs to controller actions automatically): - # resources :products - - # Example resource route with options: - # resources :products do - # member do - # get 'short' - # post 'toggle' - # end - # - # collection do - # get 'sold' - # end - # end - - # Example resource route with sub-resources: - # resources :products do - # resources :comments, :sales - # resource :seller - # end - - # Example resource route with more complex sub-resources: - # resources :products do - # resources :comments - # resources :sales do - # get 'recent', on: :collection - # end - # end - - # Example resource route with concerns: - # concern :toggleable do - # post 'toggle' - # end - # resources :posts, concerns: :toggleable - # resources :photos, concerns: :toggleable - - # Example resource route within a namespace: - # namespace :admin do - # # Directs /admin/products/* to Admin::ProductsController - # # (app/controllers/admin/products_controller.rb) - # resources :products - # end + root to: 'welcome#index' + + get '/sessions/new' => 'sessions#new', as: :login + get '/users/new' => 'users#new', as: :signup + + get "/logout" => "sessions#destroy", as: :logout + + get '/cart' => 'orders#cart', as: :cart + + delete 'cart/clear_cart' => 'orders#clear_cart', as: :clear_cart + + delete '/cart/orderitems/:id' => 'orderitems#destroy', as: :orderitems_delete + + patch '/cart/pay' => 'orders#pay', as: :pay + + get '/cart/checkout' => 'orders#checkout', as: :checkout + + get '/orders/:id/confirm' => 'orders#confirm', as: :order_confirm + + patch '/orderitems/:id/ship' => 'orderitems#ship', as: :ship + + patch 'orderitems/:id/update' => 'orderitems#update', as: :orderitems_update + + patch 'orders/:id/finalize' => 'orders#finalize', as: :order_finalize + + patch 'orders/:id/cancel_as_guest' => 'orders#cancel_as_guest', as: :order_cancel_as_guest + + post '/products/:id/buy' => 'products#buy', as: :buy + + get '/users/:id/dash' => 'users#dash', as: :user_dash + + get 'users/:id/order_dash' => 'users#order_dash', as: :user_order_dash + + get '/users/:id/products' => 'users#product_dash', as: :user_products_dash + + patch '/products/:id/retire' => 'products#retire', as: :retire + + resources :sessions, :only => [:new, :create] + resources :users + resources :products do + post "/review", to: "products#review" + end + resources :orders + resources :categories end diff --git a/db/migrate/20151208182449_create_users.rb b/db/migrate/20151208182449_create_users.rb new file mode 100644 index 0000000000..3346f3127e --- /dev/null +++ b/db/migrate/20151208182449_create_users.rb @@ -0,0 +1,12 @@ +class CreateUsers < ActiveRecord::Migration + def change + create_table :users do |t| + t.string :username + t.string :email_address + t.string :password + t.string :password_confirmation + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20151208183019_create_products.rb b/db/migrate/20151208183019_create_products.rb new file mode 100644 index 0000000000..db1db30e31 --- /dev/null +++ b/db/migrate/20151208183019_create_products.rb @@ -0,0 +1,14 @@ +class CreateProducts < ActiveRecord::Migration + def change + create_table :products do |t| + t.string :name + t.integer :price + t.integer :user_id + t.integer :stock + t.string :photo_url + t.string :description + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20151208183259_create_categories.rb b/db/migrate/20151208183259_create_categories.rb new file mode 100644 index 0000000000..e041ff42c4 --- /dev/null +++ b/db/migrate/20151208183259_create_categories.rb @@ -0,0 +1,10 @@ +class CreateCategories < ActiveRecord::Migration + def change + create_table :categories do |t| + t.string :name + t.string :description + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20151208184357_create_orderitems.rb b/db/migrate/20151208184357_create_orderitems.rb new file mode 100644 index 0000000000..87588061ac --- /dev/null +++ b/db/migrate/20151208184357_create_orderitems.rb @@ -0,0 +1,11 @@ +class CreateOrderitems < ActiveRecord::Migration + def change + create_table :orderitems do |t| + t.integer :product_id + t.integer :order_id + t.integer :quantity + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20151208184432_create_orders.rb b/db/migrate/20151208184432_create_orders.rb new file mode 100644 index 0000000000..03b7c599d3 --- /dev/null +++ b/db/migrate/20151208184432_create_orders.rb @@ -0,0 +1,18 @@ +class CreateOrders < ActiveRecord::Migration + def change + create_table :orders do |t| + t.integer :item_id + t.string :status + t.string :cc_name + t.string :email_address + t.string :mailing_address + t.integer :cc_number + t.integer :cc_exp + t.integer :cc_ccv + t.integer :zip + t.integer :user_id + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20151208185250_create_join_table.rb b/db/migrate/20151208185250_create_join_table.rb new file mode 100644 index 0000000000..65737c0473 --- /dev/null +++ b/db/migrate/20151208185250_create_join_table.rb @@ -0,0 +1,8 @@ +class CreateJoinTable < ActiveRecord::Migration + def change + create_join_table :categories, :products do |t| + # t.index [:category_id, :product_id] + # t.index [:product_id, :category_id] + end + end +end diff --git a/db/migrate/20151209025552_add_retiredto_products.rb b/db/migrate/20151209025552_add_retiredto_products.rb new file mode 100644 index 0000000000..327adfcce1 --- /dev/null +++ b/db/migrate/20151209025552_add_retiredto_products.rb @@ -0,0 +1,5 @@ +class AddRetiredtoProducts < ActiveRecord::Migration + def change + add_column :products, :retired, :boolean + end +end diff --git a/db/migrate/20151209030131_add_user_idto_categories.rb b/db/migrate/20151209030131_add_user_idto_categories.rb new file mode 100644 index 0000000000..5032808a4a --- /dev/null +++ b/db/migrate/20151209030131_add_user_idto_categories.rb @@ -0,0 +1,5 @@ +class AddUserIdtoCategories < ActiveRecord::Migration + def change + add_column :categories, :user_id, :integer + end +end diff --git a/db/migrate/20151209030349_add_placed_atto_orders.rb b/db/migrate/20151209030349_add_placed_atto_orders.rb new file mode 100644 index 0000000000..6f9080a146 --- /dev/null +++ b/db/migrate/20151209030349_add_placed_atto_orders.rb @@ -0,0 +1,5 @@ +class AddPlacedAttoOrders < ActiveRecord::Migration + def change + add_column :orders, :placed_at, :datetime + end +end diff --git a/db/migrate/20151209030637_remove_user_idfrom_orders.rb b/db/migrate/20151209030637_remove_user_idfrom_orders.rb new file mode 100644 index 0000000000..3589338a48 --- /dev/null +++ b/db/migrate/20151209030637_remove_user_idfrom_orders.rb @@ -0,0 +1,5 @@ +class RemoveUserIdfromOrders < ActiveRecord::Migration + def change + remove_column :orders, :user_id, :integer + end +end diff --git a/db/migrate/20151209172627_create_reviews.rb b/db/migrate/20151209172627_create_reviews.rb new file mode 100644 index 0000000000..641c9b4a42 --- /dev/null +++ b/db/migrate/20151209172627_create_reviews.rb @@ -0,0 +1,11 @@ +class CreateReviews < ActiveRecord::Migration + def change + create_table :reviews do |t| + t.integer :rating + t.integer :product_id + t.string :body + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20151209174339_change_ccv_to_cvv.rb b/db/migrate/20151209174339_change_ccv_to_cvv.rb new file mode 100644 index 0000000000..5660f3e9c1 --- /dev/null +++ b/db/migrate/20151209174339_change_ccv_to_cvv.rb @@ -0,0 +1,6 @@ +class ChangeCcvToCvv < ActiveRecord::Migration + def change + remove_column :orders, :cc_ccv, :integer + add_column :orders, :cc_cvv, :integer + end +end diff --git a/db/migrate/20151209180850_remove_itemid_from_order.rb b/db/migrate/20151209180850_remove_itemid_from_order.rb new file mode 100644 index 0000000000..e46e12bdc3 --- /dev/null +++ b/db/migrate/20151209180850_remove_itemid_from_order.rb @@ -0,0 +1,5 @@ +class RemoveItemidFromOrder < ActiveRecord::Migration + def change + remove_column :orders, :item_id, :integer + end +end diff --git a/db/migrate/20151209222155_change_retiredin_products.rb b/db/migrate/20151209222155_change_retiredin_products.rb new file mode 100644 index 0000000000..d076ec77f4 --- /dev/null +++ b/db/migrate/20151209222155_change_retiredin_products.rb @@ -0,0 +1,5 @@ +class ChangeRetiredinProducts < ActiveRecord::Migration + def change + change_column_default :products, :retired, false + end +end diff --git a/db/migrate/20151209233649_creditcard_data_to_strings.rb b/db/migrate/20151209233649_creditcard_data_to_strings.rb new file mode 100644 index 0000000000..60638dc6a3 --- /dev/null +++ b/db/migrate/20151209233649_creditcard_data_to_strings.rb @@ -0,0 +1,8 @@ +class CreditcardDataToStrings < ActiveRecord::Migration + def change + remove_column :orders, :cc_cvv, :integer + remove_column :orders, :cc_exp, :integer + add_column :orders, :cc_exp, :string + add_column :orders, :cc_cvv, :string + end +end diff --git a/db/migrate/20151210032304_puttingpassworddigestinuser.rb b/db/migrate/20151210032304_puttingpassworddigestinuser.rb new file mode 100644 index 0000000000..79821296e4 --- /dev/null +++ b/db/migrate/20151210032304_puttingpassworddigestinuser.rb @@ -0,0 +1,7 @@ +class Puttingpassworddigestinuser < ActiveRecord::Migration + def change + add_column :users, :password_digest, :string + remove_column :users, :password, :string + remove_column :users, :password_confirmation, :string + end +end diff --git a/db/migrate/20151210044905_cc_number_into_string.rb b/db/migrate/20151210044905_cc_number_into_string.rb new file mode 100644 index 0000000000..1a9dceb602 --- /dev/null +++ b/db/migrate/20151210044905_cc_number_into_string.rb @@ -0,0 +1,5 @@ +class CcNumberIntoString < ActiveRecord::Migration + def change + change_column(:orders, :cc_number, :string) + end +end diff --git a/db/migrate/20151215181629_add_status_to_orderitem.rb b/db/migrate/20151215181629_add_status_to_orderitem.rb new file mode 100644 index 0000000000..76e9384cd0 --- /dev/null +++ b/db/migrate/20151215181629_add_status_to_orderitem.rb @@ -0,0 +1,5 @@ +class AddStatusToOrderitem < ActiveRecord::Migration + def change + add_column(:orderitems, :status, :string) + end +end diff --git a/db/migrate/20151218003607_orderitems_default_quantity.rb b/db/migrate/20151218003607_orderitems_default_quantity.rb new file mode 100644 index 0000000000..8d086777b8 --- /dev/null +++ b/db/migrate/20151218003607_orderitems_default_quantity.rb @@ -0,0 +1,5 @@ +class OrderitemsDefaultQuantity < ActiveRecord::Migration + def change + change_column(:orderitems, :quantity, :integer, :default => 1) + end +end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000000..d2bdf32f36 --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,80 @@ +# encoding: UTF-8 +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema.define(version: 20151218003607) do + + create_table "categories", force: :cascade do |t| + t.string "name" + t.string "description" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "user_id" + end + + create_table "categories_products", id: false, force: :cascade do |t| + t.integer "category_id", null: false + t.integer "product_id", null: false + end + + create_table "orderitems", force: :cascade do |t| + t.integer "product_id" + t.integer "order_id" + t.integer "quantity", default: 1 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "status" + end + + create_table "orders", force: :cascade do |t| + t.string "status" + t.string "cc_name" + t.string "email_address" + t.string "mailing_address" + t.string "cc_number" + t.integer "zip" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.datetime "placed_at" + t.string "cc_exp" + t.string "cc_cvv" + end + + create_table "products", force: :cascade do |t| + t.string "name" + t.integer "price" + t.integer "user_id" + t.integer "stock" + t.string "photo_url" + t.string "description" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "retired", default: false + end + + create_table "reviews", force: :cascade do |t| + t.integer "rating" + t.integer "product_id" + t.string "body" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "users", force: :cascade do |t| + t.string "username" + t.string "email_address" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "password_digest" + end + +end diff --git a/db/seeds.rb b/db/seeds.rb index 4edb1e857e..256940cc14 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,7 +1,558 @@ -# This file should contain all the record creation needed to seed the database with its default values. -# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). -# -# Examples: -# -# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) -# Mayor.create(name: 'Emanuel', city: cities.first) +users = [ + { username: "BeJeweled", + email_address: "jewlz@jewlz.com", + password: "123", + password_confirmation: "123" + }, + { username: "Diamonds are Forevz", + email_address: "diamonds@diamonds.com", + password: "123", + password_confirmation: "123" + }, + { username: "Ruby Tuesday", + email_address: "roob@roob.com", + password: "123", + password_confirmation: "123" + }, + { username: "Opal's Opals", + email_address: "opal@opal.com", + password: "123", + password_confirmation: "123" + }, + { username: "Hard Rock", + email_address: "rock@rock.com", + password: "123", + password_confirmation: "123" + }, + { username: "Put a Ring on it", + email_address: "ring@ring.com", + password: "123", + password_confirmation: "123" + }, + { username: "Crystal's Crystals", + email_address: "crystal@crystal.com", + password: "123", + password_confirmation: "123" + }, + { username: "The Bling Ring", + email_address: "bling@ring.com", + password: "123", + password_confirmation: "123" + }, + { username: "Hot Rocks", + email_address: "hot@rocks.com", + password: "123", + password_confirmation: "123" + }, + { username: "Treasure Trolls Gems", + email_address: "troll@troll.com", + password: "123", + password_confirmation: "123" + }, + { username: "Jewel's Jewels", + email_address: "jewel@jewel.com", + password: "123", + password_confirmation: "123" + }, + { username: "Shine Theory", + email_address: "shine@theory.com", + password: "123", + password_confirmation: "123" + }, + { username: "Twinkles Gem Shop", + email_address: "twinkle@twinkle.com", + password: "123", + password_confirmation: "123" + }, + { username: "Zanzabar Gems", + email_address: "zanzabar@zanzabar.com", + password: "123", + password_confirmation: "123" + }, + { username: "Rings n Things", + email_address: "rings@things.com", + password: "123", + password_confirmation: "123" + }, + { username: "Gems on Gems on Gems", + email_address: "gems@gems.com", + password: "123", + password_confirmation: "123" + }, + { username: "Jem's Gems", + email_address: "audrey@audrey.com", + password: "123", + password_confirmation: "123" + }, + { username: "Rocky's Rock Shop", + email_address: "rocky@rock.com", + password: "123", + password_confirmation: "123" + } +] + +orders = [ + { status: "pending", + cc_name: "Hairy McNairy", + email_address: "hair@hair.com", + mailing_address: "123 Holly Lane", + cc_number: 376254415526143, + cc_exp: "11/16", + cc_cvv: "563", + zip: 45346, + placed_at: rand(1.year.ago..Time.now) + }, + { status: "paid", + cc_name: "Shea M Beedy", + email_address: "shea@sh.com", + mailing_address: "3423 Jello Street", + cc_number: 349309788615040, + cc_exp: "10/16", + cc_cvv: "643", + zip: 03664, + placed_at: rand(1.year.ago..Time.now) + }, + { status: "cancelled", + cc_name: "Larry B. Goode", + email_address: "larbear@lar.com", + mailing_address: "653 Octopus Ave", + cc_number: 373196399237895, + cc_exp: "11/17", + cc_cvv: "909", + zip: 98245, + placed_at: rand(1.year.ago..Time.now) + }, + { status: "pending", + cc_name: "Holly Juniper", + email_address: "carebearz@gmail.com", + mailing_address: "385 Woodstock Lane", + cc_number: 378057410243640, + cc_exp: "09/17", + cc_cvv: "455", + zip: 39653, + placed_at: rand(1.year.ago..Time.now) + }, + { status: "paid", + cc_name: "Amy Spaghetti", + email_address: "meatballs@yahoo.com", + mailing_address: "5333 Mockingbird Way", + cc_number: 6011922064827826, + cc_exp: "07/18", + cc_cvv: "436", + zip: 63578, + placed_at: rand(1.year.ago..Time.now) + }, + { status: "cancelled", + cc_name: "Henrietta Jane", + email_address: "soccermom435@yahoo.com", + mailing_address: "1000 15th Ave", + cc_number: 4539570245560697, + cc_exp: "11/17", + cc_cvv: "355", + zip: 46788, + placed_at: rand(1.year.ago..Time.now) + }, + { status: "pending", + cc_name: "Kay O'Hara", + email_address: "cutiepootie@gmail.com", + mailing_address: "45 South James St", + cc_number: 4024007126415131, + cc_exp: "11/19", + cc_cvv: "087", + zip: 35985, + placed_at: rand(1.year.ago..Time.now) + }, + { status: "paid", + cc_name: "Hollis O'Leary", + email_address: "rainbowjoy344@hotmail.com", + mailing_address: "22 Pine St", + cc_number: 4929652131634238, + cc_exp: "05/19", + cc_cvv: "456", + zip: 98357, + placed_at: rand(1.year.ago..Time.now) + }, + { status: "cancelled", + cc_name: "Andy Bahl", + email_address: "batman635@hotmail.com", + mailing_address: "5345 East Republican St", + cc_number: 4556996862163598, + cc_exp: "06/19", + cc_cvv: "942", + zip: 97446, + placed_at: rand(1.year.ago..Time.now) + }, + { status: "pending", + cc_name: "John Carlisle", + email_address: "jcarl@gmail.com", + mailing_address: "653 Gorge Way", + cc_number: 5110538084994719, + cc_exp: "06/18", + cc_cvv: "674", + zip: 19583, + placed_at: rand(1.year.ago..Time.now) + }, + { status: "paid", + cc_name: "George Schloeff", + email_address: "yoohoo@yahoo.com", + mailing_address: "74 West Highland Road", + cc_number: 5303446871574552, + cc_exp: "06/19", + cc_cvv: "333", + zip: 84573, + placed_at: rand(1.year.ago..Time.now) + }, + { status: "cancelled", + cc_name: "Mary Schleiblet", + email_address: "ladydame@yahoo.com", + mailing_address: "800 16th Ave", + cc_number: 5303886871574552, + cc_exp: "06/18", + cc_cvv: "3334", + zip: 84574, + placed_at: rand(1.year.ago..Time.now) + }, + { status: "cancelled", + cc_name: "Georgina Tartsey", + email_address: "prettyinpink@yahoo.com", + mailing_address: "79 West Highland Road", + cc_number: 5403446871574553, + cc_exp: "07/19", + cc_cvv: "433", + zip: 84583, + placed_at: rand(1.year.ago..Time.now) + }, + { status: "paid", + cc_name: "Jorge Delgotto", + email_address: "ilovepeaches@yahoo.com", + mailing_address: "800 Stinky Road", + cc_number: 53034444471574552, + cc_exp: "06/09", + cc_cvv: "393", + zip: 84573, + placed_at: rand(1.year.ago..Time.now) + }, + { status: "pending", + cc_name: "Alberta Albertson", + email_address: "bigbassfisher@yahoo.com", + mailing_address: "9 East Westland Road", + cc_number: 53034468744435722, + cc_exp: "06/20", + cc_cvv: "338", + zip: 44444, + placed_at: rand(1.year.ago..Time.now) + }, + { status: "cancelled", + cc_name: "Al Sharkton", + email_address: "tunafish35@yahoo.com", + mailing_address: "39 Red Rock Road", + cc_number: 5325283615453866, + cc_exp: "04/16", + cc_cvv: "467", + zip: 79664, + placed_at: rand(1.year.ago..Time.now) + } +] + +orderitems = [ + { product_id:33 , order_id: 1, quantity: 1 }, + { product_id: 32, order_id: 2, quantity: 2 }, + { product_id: 31, order_id: 3, quantity: 1 }, + { product_id: 30, order_id: 4, quantity: 1 }, + { product_id: 29, order_id: 5, quantity: 1 }, + { product_id: 28, order_id: 6, quantity: 1}, + { product_id: 27, order_id: 7, quantity: 2}, + { product_id: 25, order_id: 8, quantity: 1}, + { product_id: 24, order_id: 9, quantity: 1}, + { product_id: 23, order_id: 10, quantity: 1}, + { product_id: 22, order_id: 11, quantity: 2}, + { product_id: 21, order_id: 12, quantity: 1}, + { product_id: 19, order_id: 13, quantity: 2}, + { product_id: 18, order_id: 14, quantity: 3}, + { product_id: 17, order_id: 15, quantity: 1}, + { product_id: 44, order_id: 16, quantity: 1}, + { product_id: 16, order_id: 1, quantity: 1}, + { product_id: 15, order_id: 2, quantity: 2}, + { product_id: 14, order_id: 3, quantity: 3}, + { product_id: 13, order_id: 4, quantity: 2}, + { product_id: 12, order_id: 5, quantity: 1}, + { product_id: 11, order_id: 6, quantity: 1}, + { product_id: 10, order_id: 7, quantity: 1}, + { product_id: 43, order_id: 8, quantity: 1}, + { product_id: 42, order_id: 9, quantity: 1}, + { product_id: 41, order_id: 10, quantity: 1}, + { product_id: 40, order_id: 11, quantity: 1}, + { product_id: 39, order_id: 12, quantity: 1}, + { product_id:31 , order_id: 1, quantity: 1 }, + { product_id: 35, order_id: 2, quantity: 2 }, + { product_id: 30, order_id: 3, quantity: 1 }, + { product_id: 3, order_id: 4, quantity: 1 }, + { product_id: 2, order_id: 5, quantity: 1 }, + { product_id: 1, order_id: 6, quantity: 1}, + { product_id: 5, order_id: 7, quantity: 2}, + { product_id: 4, order_id: 8, quantity: 1}, + { product_id: 6, order_id: 9, quantity: 1}, + { product_id: 7, order_id: 10, quantity: 1}, + { product_id: 8, order_id: 11, quantity: 2}, + { product_id: 9, order_id: 12, quantity: 1}, + { product_id: 10, order_id: 13, quantity: 2}, + { product_id: 11, order_id: 14, quantity: 3}, + { product_id: 50, order_id: 15, quantity: 1}, + { product_id: 45, order_id: 16, quantity: 1}, + { product_id: 17, order_id: 1, quantity: 1}, + { product_id: 1, order_id: 2, quantity: 2}, + { product_id: 12, order_id: 3, quantity: 3}, + { product_id: 17, order_id: 4, quantity: 2}, + { product_id: 19, order_id: 5, quantity: 1}, + { product_id: 25, order_id: 6, quantity: 1}, + { product_id: 52, order_id: 7, quantity: 1}, + { product_id: 50, order_id: 8, quantity: 1}, + { product_id: 49, order_id: 9, quantity: 1}, + { product_id: 26, order_id: 10, quantity: 1}, + { product_id: 23, order_id: 11, quantity: 1}, + { product_id: 3, order_id: 12, quantity: 1}, + { product_id: 13, order_id: 2, quantity: 2}, + { product_id: 1, order_id: 3, quantity: 3}, + { product_id: 7, order_id: 4, quantity: 2}, + { product_id: 29, order_id: 5, quantity: 1}, + { product_id: 15, order_id: 6, quantity: 1}, + { product_id: 43, order_id: 7, quantity: 1}, + { product_id: 51, order_id: 8, quantity: 1}, + { product_id: 4, order_id: 9, quantity: 1}, + { product_id: 6, order_id: 10, quantity: 1}, + { product_id: 13, order_id: 11, quantity: 1}, + { product_id: 9, order_id: 12, quantity: 1} +] + +reviews = [ + { rating: 1, product_id: 1, body: "Hideous. disappointed. returning it."}, + { rating: 5, product_id: 2, body: "My daughter LOVED it!"}, + { rating: 4, product_id: 3, body: "Not as shiny as in the picture, but still nice."}, + { rating: 3, product_id: 4, body: "Pretty high quality gem."}, + { rating: 1, product_id: 5, body: "Looks NOTHING like the photo. Awful."}, + { rating: 5, product_id: 6, body: "So dazzling! Love."}, + { rating: 3, product_id: 7, body: "Not worth the money, but a good product."}, + { rating: 4, product_id: 8, body: "Cuuuuute."}, + { rating: 5, product_id: 9, body: "My fiancee proposed to me with this! I love it!!"}, + { rating: 1, product_id: 10, body: "Broke a day after arriving."}, + { rating: 4, product_id: 11, body: "Looks a little cheaper than in the photo, but overall I like it."}, + { rating: 3, product_id: 12, body: "Not really my style. Kind of tacky."}, + { rating: 5, product_id: 13, body: "I'll be buying another one for my husband!!"}, + { rating: 5, product_id: 23, body: "Getting this as a holiday gift for everyone I know!"}, + { rating: 5, product_id: 24, body: "Dazzling. Just dazzling."}, + { rating: 5, product_id: 25, body: "Absolutely stunning."}, + { rating: 2, product_id: 26, body: "Honestly, not very flattering."}, + { rating: 5, product_id: 27, body: "My wife cried when she opened it. Out of joy!"}, + { rating: 2, product_id: 28, body: "Not sure what they were going for with this cut of gem..."}, + { rating: 1, product_id: 29, body: "It fell apart a week later."}, + { rating: 5, product_id: 30, body: "Absolutely worth the money!"}, + { rating: 4, product_id: 40, body: "Not the best cut, but a decent bargain."}, + { rating: 3, product_id: 50, body: "It's okay. I've seen more impressive."}, + { rating: 1, product_id: 41, body: "Ugh. Waaaay too shiny, it hurts my eyes."}, + { rating: 2, product_id: 42, body: "Gave me a headache from looking at it."}, + { rating: 5, product_id: 43, body: "My aunt looooooved it!"}, + { rating: 4, product_id: 44, body: "Looks VERY nice against my skin."}, + { rating: 5, product_id: 45, body: "oh my god...stunning gem."}, + { rating: 1, product_id: 46, body: "gross."}, + { rating: 2, product_id: 47, body: "Who would WANT this? ripoff."}, + { rating: 5, product_id: 48, body: "I'll be back for another when I can afford it!"}, + { rating: 4, product_id: 49, body: "Quality product- well chiseled."}, + { rating: 4, product_id: 50, body: "I wish it were bigger, but it's pretty cool."}, + { rating: 5, product_id: 1, body: "Gorgeous stone!"}, + { rating: 5, product_id: 10, body: "This is EXACTLY what I was looking for for my anniversary."}, + { rating: 2, product_id: 11, body: "Smaller than it looks in the photo."}, + { rating: 1, product_id: 12, body: "Buyer beware- it's REALLY cheap."}, + { rating: 2, product_id: 13, body: "Scratched my child while he was playing with it."}, + { rating: 1, product_id: 14, body: "NOT pet safe. My cat ate it and I had to take him to the vet."}, + { rating: 5, product_id: 15, body: "Makes me feel young again!"}, + { rating: 4, product_id: 16, body: "I want to bejewel my whole body with this!"}, + { rating: 2, product_id: 17, body: "NOT child safe!! My toddler ate three of these."}, + { rating: 1, product_id: 18, body: "It gave me a horrible allergic reaction. NOT for people with sensitive skin."}, + { rating: 2, product_id: 19, body: "Lost its luster after a short period of time."}, + { rating: 3, product_id: 20, body: "I went to have it shined and it turned green. But before that it was nice."}, + { rating: 4, product_id: 21, body: "Reeeally pretty jewel, but a little pricey for my taste."}, + { rating: 5, product_id: 22, body: "I'm getting married because of this bad boy!"}, + { rating: 1, product_id: 23, body: "My sister was wearing it and she ended up having to go to the hospital. Do NOT recommend."}, + { rating: 2, product_id: 24, body: "Not my favorite from this vendor. I think they are using a new manufacturer and the quality has dropped in recent years."}, + { rating: 5, product_id: 25, body: "I'm on my fifth marriage- this lil puppy charms them into saying yes every time."}, + { rating: 4, product_id: 26, body: "Classy. Classic. Timeless"}, + { rating: 4, product_id: 40, body: "WILL take your breath away. I love it."}, + { rating: 5, product_id: 41, body: "Timeless elegance!"}, + { rating: 5, product_id: 42, body: "My husband and I each got matching ones- they're so cute side by side!"}, + { rating: 2, product_id: 43, body: "Turned green after water got on it."}, + { rating: 5, product_id: 44, body: "hideous. disappointed. returning it."}, + { rating: 1, product_id: 45, body: "I LITERALLY think this gem has a curse on it, because bad things have been happening to me all year."}, + { rating: 1, product_id: 12, body: "I fell down the stairs after I put it on- I think it's cursed."}, + { rating: 5, product_id: 3, body: "Makes me so happy when I see it in my jewelry box every morning."}, + { rating: 5, product_id: 4, body: "My daughter wears this every day!"} +] + +products = [ + # Emerald + {retired: false, name:"Emerald Sword", price: 2040 , user_id: "1", stock: "2" , photo_url: "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSdu1XTO5gfUbPLLseSkv2QgYSoofnZ6tx3Yt3BXo2OQUMakGMQ", description: "Let this delightful emerald sword help you thwack your way through the world." }, + {retired: false, name: "Pure Emerald Block", price: 6500, user_id: "12", stock: "25", photo_url: "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcSo-egwLeTw02paY3aP79TTmx3FzJIKZqxlVDLcpAVwQ858cZdq_g", description: "Use this lovely emerald block to build all the things."}, + {name: "Fancy Pantsy Necklace", price: 600, user_id: "14", stock: "22", photo_url: "http://www.faberge.com/images/thumbs/0006090_690.jpeg", description: "Look the best at your next fancy party."}, + {name: "Gaudy Is For Lovers", price: 800, user_id: "4", stock: "1", photo_url: "http://i.ebayimg.com/00/s/MzAwWDMwMA==/z/ZiYAAOSwnDZUAAOK/$_35.JPG?set_id=2", description: "Bedeck your hands with this one-of-a-kind glory."}, + # Ruby + {name: "Ruby Sword", price: 7868, user_id: "2", stock: "5", photo_url: "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcS7u0rM40peU5eoDCl7PCmyMpsg7c1iqco_dzvQn_1c_ah8L298hGXF9AU", description: "You won't even be able to see the blood."}, + {retired: false, name: "Blood Red Shovel", price: 666, user_id: "1", stock: "5", photo_url: "http://vignette1.wikia.nocookie.net/minecraftfanfictions/images/5/5e/Ruby_shovel.png/revision/latest?cb=20120803133632", description: "Bury the bodies of your enemies in style."}, + {name: "One Ring to Rule Them All", price: 4254, user_id: "6", stock: "4", photo_url: "http://verdura.blob.core.windows.net/images/products/0578255bca9e4a539026537b0ec50fe7/large", description: "Just try to find a matching outfit for this one... "}, + {name: "Radical Ruby Ring", price: 5432, user_id: "6", stock: "55", photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRU5kK3fdZX3VXVQjR84Skk27lVwBjDV5NJnmmhSexK1CJqi8WhaQ", description: "It's a ring. With a ruby in it. "}, + {retired: true, name: "Raw Ruby Rock", price: 343, user_id: "15", stock: "3", photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTboRwcl_mhVPNT7hW03VNdENxn0bRXCto_dPuGzJNZfGTQGqUO", description: "I guess calling it a rock doesn't make you want to buy it."}, + {name: "Funny Looking Ruby", price: 453, user_id: "16", stock: "456", photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTjOjxJma6TgDA-WOw2z1w0lZ0Yvw7epBR_Uy_IRjhfQoxQUypH", description: "It's synthetic, what did you expect?"}, + {name: "Not Craisins", price: 45, user_id: "16", stock: "32", photo_url: "https://static.auctionmate.io/gr/uploads/images/255000-259999/257107/257107_1328612158.jpg", description: "Don't eat these rubies, they'll hurt your teeth."}, + {name: "Pulsing Pendant", price: 433, user_id: "11", stock: "34", photo_url: "http://www.raritetantique.com/img/products/Jewelry/Sets/Raw%20Ruby%20Set%20ring%20pendant/Vintage%20Raw%20Ruby%20Diamond%2014K%20Gold%20Ring%20Pendant%20Set%20(11).jpg", description: "Like gold fingers clenching your beating heart. It'll look great with your cheekbones."}, + {retired: true, name: "Ruby Necklace", price: 453, user_id: "3", stock: "45", photo_url: "http://www.jared.com/images/products/1333/133361004_MV_ZM_JAR.jpg", description: "It'a necklace. You put it around your neck."}, + {name: "Red Crown", price: 5353, user_id: "8", stock: "33", photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ4fLrTjmOCHPy5RdAgELSXIyw5m8IX5hHSfZuqrxqG9-Wseh8j", description: "Because you're a queen."}, + {name: "Spider Heart", price: 4532, user_id: "6", stock: "2", photo_url: "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRuxZHOkKmRQTBVQ8VUnrrGu-xMtl4E8--JKB3w34ZR29zq2926", description: "I put a spell on you, and now you're miiine... "}, + # Diamond + {name: "Geometry Like Woah", price: 5645, user_id: "2", stock: "1", photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", description: "I drew this just for you."}, + {name: "Geometry 2", price: 5435, user_id: "2", stock: "1", photo_url: "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcSEgpQiG4wS992NcEjjLVfhzBCj5pmqYLFDo4XDEQJx69DmC_O5vA", description: "Another angle, especially for you."}, + {name: "Geometry 3", price: 5354, user_id: "2", stock: "1", photo_url: "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcShLGH5v6h395Bd7I4Kvro4p1uNEpzcb1Ze8eZOXiXL_wMP8f6N8A", description: "In case you wanted something that pops. I drew it for you. Love me?"}, + {retired: true, name: "Fancy Pants Set", price: 5542, user_id: "4", stock: "4", photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtiizC6M9GRTugFfzo0mYBrM1oPk-kCKzKc4EDz0ZATCdtExRXOQ", description: "To show how much you care."}, + {name: "Every Kiss Begins With A Letter of the Alphabet", price: 43, user_id: "5", stock: "32", photo_url: "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcTDaj_MIMbt2FZIpf5a23889fpxQe0KX7Zv2lEIhHLCgh6pdH8NIw", description: "Risk: Swallowing Hazard. Keep Away From Small Children."}, + # Azurite + {name: "Ocean Pendant", price: 452, user_id: "4", stock: "4", photo_url: "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRULoT20bJYqQe9ZG0ZaWwNxohZs1CNTcy6gn4qbmJKIB5-aoSULA", description: "Hold the ocean on your chest. On your chest? Somewhere. Bring a towel."}, + {name: "Square Pendant", price: 3642, user_id: "5", stock: "4", photo_url: "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSqcsrEC9WSg7rZ_SDfMVqdYCYROTDuyCzkPM4ibA6WXnsS3DBoSQ", description: "Disclaimer: This is NOT a lava lamp."}, + {name: "Earth Day Earrings", price: 5223, user_id: "5", stock: "2", photo_url: "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcSCYoPOKaAS85w9NPGquyeS3i3EuDwOcnlUcMOud1j5uyoseRTshg", description: "Who needs shoulders when you've got ears?"}, + {name: "Rad Pretty Rock", price: 4343, user_id: "15", stock: "88", photo_url: "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcQGYDxlpcTX59vlgTzMDw0f8R6scoAi0fCImFOUSa7mYze-s4V9-g", description: "I dug it up myself."}, + {name: "Radioactive Earrings", price: 5353, user_id: "13", stock: "7", photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRq9o_V-qgosXZDGZ09vFmRn662HHEdtb4J_tO3-6kzKwWIw2w", description: "Just kidding. I swear.."}, +# Saphhire + {name: "Floral Pendant", price: 5434, user_id: "3", stock: "6", photo_url: "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcQCr5oLFJAVGA_Yk6lO9V9_2vVxObHr8eiq4FatLm4NUK9Q8qGy", description: "It's flowery and stuff."}, + {name: "Sapphire Studs", price: 3522, user_id: "7", stock: "5", photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRAIXAGZ305zjSNF5G5RUEsqTlJqhZD7HI529vAHdBIBIya3olG", description: "Make your ears have more blue."}, + {name: "Swan Pendant", price: 5344, user_id: "8", stock: "43", photo_url: "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcT48T18ftz5Ob4bEskZVWC0UlEfxCp7D6cS5UuQs1_KSDZXBa4-", description: "You can see it if you look really hard."}, + {name: "Sails!", price: 455, user_id: "12", stock: "4325", photo_url: "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcTojfeqUe8S2DR6CdpHIZ6udS3UPwzpN4D56W7OaaY_7zSlu4vD4Q", description: "Sail away, my dear."}, + {name: "A Three-fer", price: 3235, user_id: "4", stock: "34", photo_url: "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRXSnmM4i_3B1_I9K9CQ1M14jV5gn_GosC613w75JpMFv_x_OFESw", description: "Three for the price of three!"}, +# Quartz + {name: "I Carry your Heart", price: 3455, user_id: "11", stock: "4", photo_url: "http://i.ebayimg.com/00/s/MzAwWDMwMA==/z/n~EAAOSwVFlT~-CI/$_35.JPG?set_id=2", description: "... I carry it in my heart"}, + {name: "Moon Ring", price: 2356, user_id: "13", stock: "2", photo_url: "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcT8WoXh7XoD6nrqUMQDu-lNAcfSXauMNz0bzSPBIKJafWQCKPb_", description: "Moon, not mood."}, + {name: "Studly Studs", price: 425, user_id: "13", stock: "13", photo_url: "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRugLdkSKwolyJaIW36Ss2HfgGRKB-eJxJJJsoWEQjTTlGSqZws", description: "Studly. Get it? Heh."}, + {name: "Stabby Rose", price: 4325, user_id: "18", stock: "552", photo_url: "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRQXU_7xJiy0xjdnDJcowY5ZUZcjyqVYaup9wk7mI-JxTSB9fPc", description: "Fashion AND function."}, + {retired: true, name: "Purdy Pink Rock", price: 4535, user_id: "", stock: "11", photo_url: "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcTDoDZLerT9aF8YAccRznJvyuFMpymri0e_Rlb6JnEj_yTgkHGIWw", description: "it's worth it, I swear."}, + {name: "A Thing", price: 3456, user_id: "16", stock: "3", photo_url: "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSICTPb__nMJZfrKRpQPChCru24VOXtTYhKIX3wmo7Ie-xrR9cTkQ", description: "Would be a great paperweight."}, + {name: "Clear Rock", price: 542, user_id: "12", stock: "3", photo_url: "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcScL2Au5edYrPpNNddkuNk20OmxspUfIqDmLyTg8P_5cI6nj0k7Fg", description: "Look at those crsip edges."}, + {name: "Prettier Pink Rock", price: 4356, user_id: "18", stock: "4", photo_url: "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQeBacGzU61npNBaFDxetu2v9n_dQw8XJa9_Z08eAfEGkLXqOFL", description: "Throw it at someone if you need."}, +# Amethyst + {name: "Functional Paperweight", price: 3225, user_id: "18", stock: "3", photo_url: "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcR9ZdYBT9RPsNPtRq4Nv3s57KpkrPZUM54lBUmzVGH-KSMAbILPIQ", description: "Toss at your enemies, or pet for comfort."}, + {name: "Egg on Stand", price: 3534, user_id: "8", stock: "4", photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT-UyhnUBMJ8rsUhrhY7ntq688MTCzd7U_wjNq5Ezmzu-dIKqcKQA", description: "Because of course you need an inedbile egg. The gold stand is free!"}, + {name: "Flat Geode Thing", price: 4245, user_id: "9", stock: "4", photo_url: "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcQa-wHb6aNhafTkibBQr1j1OtXecS2q_acji6E0fWVeSR5mWecxxQ", description: "Not a piece of sandwich bread."}, + {name: "Amethyst Sword", price: 5425, user_id: "10", stock: "2", photo_url: "http://www.orespawn.com/uploads/2/5/3/5/25358181/2043216_orig.png", description: "Thwack thine enemies."}, + {name: "Heart on Her Finger", price: 542, user_id: "17", stock: "3", photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSDf9QsBbInlxPl_fXZSSU0E46zh2lk5nm71nQxeMvi8RhzUUpX", description: "Because sleeves are for chumps."}, + {retired: true, name: "Flutter-by Butterfly", price: 432, user_id: "7", stock: "5", photo_url: "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSj21LIRFpwLJ717Nl3NFLq001uUnyW5v2Yr_czZ6B4kjAtYUK0", description: "Disclaimer: It doesn't really fly."}, +# Tourmaline + {name: "Jolly Rancher", price: 4323, user_id: "9", stock: "3", photo_url: "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRpAO3vwZgK_Ei7brkJLsYtLkeg7O7BH4-kJiieCFtD-D0M_WiO", description: "Not a candy necklace."}, + {name: "Jormungand", price: 5435, user_id: "10", stock: "1", photo_url: "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcQKc_QG74TfTtFvS7yzv4IjMK_bOzezHLahSIE_Dfw0j3DNZ-8hww", description: "..."}, + {name: "Gem Bracelet", price: 4324, user_id: "17", stock: "2", photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCe93wq6WsmHnNE8tZBpfebGqZb3xgR94Te0uwMLH2H9M-RfUwRg", description: "Can't pick one color? Get 'em all!"}, + {name: "Some Earrings", price: 4352, user_id: "9", stock: "2", photo_url: "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRpA5O0n89dJERD3xRNQ8VJ2bpgO0uMvlqp4ihw8Yt1Pb8TIhbQEw", description: "Make sure their ears are pierced first."}, + {name: "Radioactive Butterfly", price: 4522, user_id: "14", stock: "4", photo_url: "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTfeTfBprAtSAx30yerUy-Ps-DEHGiPMjgYxRfL126tlFE3lqAThw", description: "Not proven to cause cancer in humans."}, + {retired: true, name: "Inedible Watermelon", price: 3252, user_id: "7", stock: "2", photo_url: "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcQuR4zzXZ08xSF44BfkuKjyEMV53JSEppiysKf-L-YokMv2wVwdcQ", description: "Disclaimer: not a ring-pop."}, + +# Turquoise + {name: "Turquoise Set", price: 342, user_id: "17", stock: "3", photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRAT_lQaYED2EAswqwQ7LAfUrPTOcyvRathjpdNNoEv4VLfl6ty", description: "No need to mix and match."}, + {name: "Probably Fake Turquoise Rings", price: 544, user_id: "10", stock: "6765", photo_url: "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcQoGPq0oTIxG8tXbaUH9YNqfZQWjS4N9oqGVES-iGt7-UHphsiL", description: "But you look cool until your fingers are green."}, + {name: "T-Chainz", price: 3255, user_id: "14", stock: "23", photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRLXniy8gk5MCCGIrDXINEaYRffW0UkVmN1-sOAUoCC1LYNghI5ug", description: "Cuter than handcuffs."}, + {name: "T-Earth", price: 4325, user_id: "15", stock: "2", photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQlkA8Z3x1WgIFcMxPAYnPB0ViPmYIQPyDyFUAQYlT3vqvvp6ck9w", description: "I actually like this one."}, +] + +categories = [ + {name: "Emerald"}, + {name: "Ruby"}, + {name: "Diamond"}, + {name: "Sapphire"}, + {name: "Quartz"}, + {name: "Amethyst"}, + {name: "Tourmaline"}, + {name: "Turquoise"}, +] + +category_products = [ + {category_id: "1", product_id: "1"}, + {category_id: "1", product_id: "2"}, + {category_id: "1", product_id: "3"}, + {category_id: "1", product_id: "4"}, + {category_id: "2", product_id: "5"}, + {category_id: "2", product_id: "6"}, + {category_id: "2", product_id: "7"}, + {category_id: "2", product_id: "8"}, + {category_id: "2", product_id: "9"}, + {category_id: "2", product_id: "10"}, + {category_id: "2", product_id: "11"}, + {category_id: "2", product_id: "12"}, + {category_id: "2", product_id: "13"}, + {category_id: "2", product_id: "14"}, + {category_id: "2", product_id: "15"}, + {category_id: "3", product_id: "16"}, + {category_id: "3", product_id: "17"}, + {category_id: "3", product_id: "18"}, + {category_id: "3", product_id: "19"}, + {category_id: "3", product_id: "20"}, + {category_id: "11", product_id: "21"}, + {category_id: "11", product_id: "22"}, + {category_id: "11", product_id: "23"}, + {category_id: "11", product_id: "24"}, + {category_id: "11", product_id: "25"}, + {category_id: "4", product_id: "26"}, + {category_id: "4", product_id: "27"}, + {category_id: "4", product_id: "28"}, + {category_id: "4", product_id: "29"}, + {category_id: "4", product_id: "30"}, + {category_id: "5", product_id: "31"}, + {category_id: "5", product_id: "32"}, + {category_id: "5", product_id: "33"}, + {category_id: "5", product_id: "34"}, + {category_id: "5", product_id: "35"}, + {category_id: "5", product_id: "36"}, + {category_id: "5", product_id: "37"}, + {category_id: "5", product_id: "38"}, + {category_id: "6", product_id: "39"}, + {category_id: "6", product_id: "40"}, + {category_id: "6", product_id: "41"}, + {category_id: "6", product_id: "42"}, + {category_id: "6", product_id: "43"}, + {category_id: "6", product_id: "44"}, + {category_id: "7", product_id: "45"}, + {category_id: "7", product_id: "46"}, + {category_id: "7", product_id: "47"}, + {category_id: "7", product_id: "48"}, + {category_id: "7", product_id: "49"}, + {category_id: "7", product_id: "50"}, + {category_id: "8", product_id: "51"}, + {category_id: "8", product_id: "52"}, + {category_id: "8", product_id: "53"}, + {category_id: "8", product_id: "54"} +] + +products.each do |p| + prod = Product.new(p) + prod.save(validate: false) +end + +categories.each do |c| + cat = Category.new(c) + cat.save(validate: false) +end + +orderitems.each do |o| + orditem = Orderitem.new(o) + orditem.save(validate: false) +end + +users.each do |u| + user = User.new(u) + user.save(validate: false) +end + +orders.each do |o| + order = Order.new(o) + order.save(validate: false) +end + +reviews.each do |r| + review = Review.new(r) + review.save(validate: false) +end + +category_products.each do |c| + catprod = CategoriesProduct.new(c) + catprod.save(validate: false) +end diff --git a/erd.pdf b/erd.pdf new file mode 100644 index 0000000000..2aef54f26f Binary files /dev/null and b/erd.pdf differ diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb new file mode 100644 index 0000000000..c6e3534ec8 --- /dev/null +++ b/spec/controllers/application_controller_spec.rb @@ -0,0 +1,12 @@ +require 'rails_helper' +require 'support/app_controller' + +RSpec.describe ApplicationController, type: :controller do + + describe "only_current_user" do + it "only allows current user access" do + + end + end + +end \ No newline at end of file diff --git a/spec/controllers/categories_controller_spec.rb b/spec/controllers/categories_controller_spec.rb new file mode 100644 index 0000000000..6d8e964023 --- /dev/null +++ b/spec/controllers/categories_controller_spec.rb @@ -0,0 +1,67 @@ +require 'rails_helper' +require 'support/app_controller' + + +RSpec.describe CategoriesController, type: :controller do + + let(:create_params) do { + name: 'Category' + } + + end + + let (:show_item) {Category.create(create_params)} + + it "renders the show view" do + get :show, id: show_item.id + expect(response.status).to eq 200 + end + + describe "GET 'new'" do + it "renders new view" do + get :new + expect(subject).to render_template :new if @current_user != nil + end + end + + describe "POST 'create'" do + let(:user) do + User.create(username: "Mister", + email_address: "stud@manly.com", + password: "pw", + password_confirmation: "pw") + end + + let(:good_params) do + { + category: { + name: "Rock" + } + } + end + + let(:bad_params) do + { + category: { + name: nil + } + } + end + + before :each do + session[:user_id] = user.id + end + + it "redirects to products index page when good params are passed" do + post :create, good_params.merge(id: 1) + expect(subject).to redirect_to user_products_dash_path(user.id) + end + + it "renders the edit template when bad params are passed" do + post :create, bad_params + expect(subject).to render_template :new + end + end + + it_behaves_like "a quartzy controller" +end diff --git a/spec/controllers/orderitems_controller_spec.rb b/spec/controllers/orderitems_controller_spec.rb new file mode 100644 index 0000000000..63f198bccf --- /dev/null +++ b/spec/controllers/orderitems_controller_spec.rb @@ -0,0 +1 @@ +require 'rails_helper' diff --git a/spec/controllers/orders_controller_spec.rb b/spec/controllers/orders_controller_spec.rb new file mode 100644 index 0000000000..6a69de488b --- /dev/null +++ b/spec/controllers/orders_controller_spec.rb @@ -0,0 +1,108 @@ +require 'rails_helper' +require 'support/app_controller' + +RSpec.describe OrdersController, type: :controller do + let(:order_hash) do + { + status: "pending", + cc_name: "John Carlisle", + email_address: "jcarl@gmail.com", + mailing_address: "653 Gorge Way", + cc_number: 5110538084994719, + cc_exp: "06/18", + cc_cvv: "674", + zip: 19583 + } + end + + let(:order) do + Order.create!(order_hash) + end + + let(:cart_status) do + @cart_status + end + + describe "GET 'show'" do + it "renders the show view" do + get :show, id: order.id + expect(subject).to render_template :show + end + end + + describe "GET 'cart'" do + it "sets cart status to empty if there is no order_id in session" do + get :cart, {}, {:order_id => nil} + expect(@cart_status).to eq(nil) + expect(@order).to eq(nil) + end + it "renders the cart view" do + get :cart, {}, {:order_id => order.id } + expect(subject).to render_template :cart + end + + end + + describe "DELETE 'clear_cart'" do + it "sets the session order_id to nil" do + delete :clear_cart, {}, {:order_id => order.id } + expect(session[:order_id]).to be_nil + end + it "redirects to the root path" do + delete :clear_cart, {}, {:order_id => order.id } + expect(subject).to redirect_to(root_path) + end + end + + describe "GET 'checkout'" do + it "renders the checkout view" do + get :checkout, {}, {:order_id => order.id } + expect(subject).to render_template :checkout + end + end + + describe "GET 'confirm'" do + it "renders the confirm view" do + get :confirm, {:id => order.id}, {:order_id => order.id } + expect(subject).to render_template :confirm + end + end + + describe "PATCH 'cancel_as_guest'" do + it "updates the order's status to cancelled" do + expect(order.status).to eq("pending") + patch :cancel_as_guest, {:id => order.id}, {:order_id => order.id } + order.reload + expect(order.status).to eq("cancelled") + end + it "sets order_id in session info to nil" do + delete :cancel_as_guest, {:id => order.id}, {:order_id => order.id } + expect(session[:order_id]).to be_nil + end + it "redirects to root path" do + patch :cancel_as_guest, {:id => order.id}, {:order_id => order.id } + expect(subject).to redirect_to(root_path) + end + end + + #need to add more! + describe "PATCH 'finalize'" do + it "sets the session order_id to nil" do + patch :finalize, {:id => order.id}, {:order_id => order.id } + expect(session[:order_id]).to be_nil + end + it "redirects to root path" do + patch :finalize, {:id => order.id}, {:order_id => order.id } + expect(subject).to redirect_to(root_path) + end + end + + + + # pay + # edit + # update + # destroy + + it_behaves_like "a quartzy controller" +end diff --git a/spec/controllers/products_controller_spec.rb b/spec/controllers/products_controller_spec.rb new file mode 100644 index 0000000000..6b526fc9b0 --- /dev/null +++ b/spec/controllers/products_controller_spec.rb @@ -0,0 +1,258 @@ +require 'rails_helper' +require 'support/app_controller' + +RSpec.describe ProductsController, type: :controller do + describe "GET 'new'" do + it "renders new view" do + get :new + expect(subject).to render_template :new + end + end + + describe "POST 'create'" do + let(:user) do + User.create(username: "Mister", + email_address: "stud@manly.com", + password: "pw", + password_confirmation: "pw") + end + + let(:good_params) do + { + product:{ + name: "necklace", + price: 10, + user_id: 2, + stock: 3 + }, + categories: [] + } + end + + let(:bad_params) do + { + product:{ + name: nil, + price: nil + }, + categories: [] + } + end + + before :each do + session[:user_id] = user.id + end + + it "redirects to products index page when good params are passed" do + post :create, good_params.merge(id: 1) + expect(subject).to redirect_to product_path(user.id) + end + + it "renders the edit template when bad params are passed" do + post :create, bad_params + expect(subject).to render_template :new + end + end + + describe "GET 'edit'" do + let(:product) do + Product.create(name: "necklace", price: 10, user_id: 2, stock: 3) + end + + it "renders edit view" do + get :edit, id: product.id + expect(subject).to render_template :edit + end + end + + describe "GET 'show'" do + let(:show_product) do + Product.create(name: "necklace", price: 10, user_id: 2, stock: 3) + end + + it "renders the show view" do + get :show, id: show_product.id + expect(subject).to render_template :show + end + end + + describe "PATCH 'update'" do + before :each do + request.env["HTTP_REFERER"] = "back" + end + + let(:current_user) do + User.create(username: "FancyPants", + email_address: "fancypants@fancypants.com", + password: "123", + password_confirmation: "123") + end + + before :each do + session[:user_id] = current_user.id + end + + let(:product) do + Product.create(name: "necklace", + price: 10, + user_id: current_user.id, + stock: 3) + end + + let(:good_product_update) do + { + product: { + name: "necklace", + price: 25, + user_id: current_user.id, + stock: 3, + }, + id: product.id + } + end + + it "updates a good product" do + before_update = product.attributes + params = good_product_update + patch :update, params + product.reload + expect(product.attributes).to_not eq before_update + end + + it "redirects to product#show page" do + patch :update, good_product_update + expect(subject).to redirect_to product_path(product.id) + end + + let(:bad_product_update) do + { + product: { + name: "", + price: 10, + user_id: current_user.id, + stock: 3, + }, + id: product.id + } + end + + it "doesn't update a product with bad params" do + before_update = product.attributes + params = bad_product_update + patch :update, params + product.reload + expect(product.attributes).to eq before_update + end + + it "renders edit view" do + patch :update, bad_product_update + expect(subject).to render_template :edit + end + end + + describe "POST 'review'" do + let(:product) do + Product.create(name: "necklace", price: 10, user_id: 2, stock: 3) + end + let(:review_params) do + { + id: product.id, + review: { + rating: 4, + body: "so pretty!" + } + } + end + + it "creates a new product review" do + post :review, review_params.merge(product_id: product.id) + last = Review.last + expect(last.rating).to eq 4 + end + end + + describe "PATCH 'retire'" do + before :each do + request.env["HTTP_REFERER"] = "back" + end + + let(:product) do + Product.create(name: "necklace", + price: 10, + user_id: 1, + stock: 3) + end + + let(:update_product) do + { + id: product.id, + product: { + name: "necklace", + price: 10, + user_id: 1, + stock: 3, + retired: true + } + } + end + + + + let(:current_user) do + User.create(username: "FancyPants", + email_address: "fancypants@fancypants.com", + password: "123", + password_confirmation: "123") + end + + ## should go in model_spec + # let(:current_user2) do + # User.create(username: "SoiledPants", + # email_address: "soiledpants@soiledpants.com", + # password: "123", + # password_confirmation: "123") + # end + + before :each do + session[:user_id] = current_user.id + end + + ## should go in model_spec + # it "sets the status of a product to retired" do + # before_retired = product.retired + # patch :retire, update_product + # product.reload + # expect(product.retired).to_not eq before_retired + # end + + it "goes back to product show page on submit/update" do + patch :retire, update_product + expect(subject).to redirect_to "back" + end + + ## should go in model_spec + # it "doesn't let a user retire a product that they do not own" do + # update_product # trigger creation of product + # expect_any_instance_of(Product).not_to receive(:save) + # session[:user_id] = current_user2.id + # patch :retire, update_product + # expect(flash[:error]).to eq("You are not authorized to view this section") + # end + end + + describe "DELETE 'destroy'" do + before :each do + request.env["HTTP_REFERER"] = "back" + end + let(:product) do + Product.create(name: "necklace", price: 10, user_id: 2, stock: 3) + end + + it "redirects to products index page" do + delete :destroy, id: product.id + expect(subject).to redirect_to "back" + end + end + + it_behaves_like "a quartzy controller" +end diff --git a/spec/controllers/reviews_controller_spec.rb b/spec/controllers/reviews_controller_spec.rb new file mode 100644 index 0000000000..41a51ba479 --- /dev/null +++ b/spec/controllers/reviews_controller_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe ReviewsController, type: :controller do + +end diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb new file mode 100644 index 0000000000..98f5092293 --- /dev/null +++ b/spec/controllers/sessions_controller_spec.rb @@ -0,0 +1,33 @@ +require 'rails_helper' + +# RSpec.describe SessionsController, type: :controller do +# before :each do +# session[:user_id] = user.id +# end +# +# describe "POST 'create'" do +# let (:session_data) do +# { +# email: "info@diamonds.com", +# username: "diamonds", +# password: "password" +# } +# end +# +# it "creates an authenticated session" do +# user = User.find_by_username(session_data[:username]) +# post :create, :session_data => session_data +# expect(response).to redirect_to user_path(user.id) +# end +# end +# +# describe "DELETE #destroy" do +# +# before(:each) do +# @user = User.create :user +# sign_in @user, store: false +# delete :destroy, id: @user.auth_token +# end +# it { should respond_with 204 } +# end +# end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb new file mode 100644 index 0000000000..16bb41afa6 --- /dev/null +++ b/spec/controllers/users_controller_spec.rb @@ -0,0 +1,32 @@ +require 'rails_helper' + +RSpec.describe UsersController, type: :controller do + + let(:good_hash) do { + user: { + username: "Burp", + email_address: "thing@thing.com", + password: "this", + password_confirmation: "this" + }} + end + + let(:user) {User.create(good_hash)} + + # describe 'GET dash' do + # it "shows the user dash page" do + # get :dash, id: user.id + # expect(subject).to render_template :dash + # end + # end + describe "POST 'create'" do + it "creates a new user" do + post :create, good_hash + expect(User.count).to eq(1) + end + + it "success message upon create" do + expect(response.status).to eq 200 + end + end +end diff --git a/spec/controllers/welcome_controller_spec.rb b/spec/controllers/welcome_controller_spec.rb new file mode 100644 index 0000000000..c27183f97e --- /dev/null +++ b/spec/controllers/welcome_controller_spec.rb @@ -0,0 +1,71 @@ +require 'rails_helper' + +RSpec.describe WelcomeController, type: :controller do + + describe 'GET index' do + let(:user_hash) do { + username: "Burp", + email_address: "thing@thing.com", + password: "this", + password_confirmation: "this" + } + end + let(:second_user_hash) do { + username: "Ugh", + email_address: "athing@thing.com", + password: "this", + password_confirmation: "this" + } + end + let(:product_hash) do + {name: "Geometry Like Woahhh", + price: 5645, + stock: "1", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + retired: false + } + end + let(:second_product) do + {name: "Another Product Thing", + price: 5645245, + stock: "2", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + retired: false + } + end + let(:third_product) do + {name: "Another Thing", + price: 5645245, + stock: "2", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + retired: false + } + end + let(:fourth_product) do + {name: "Fourth product", + price: 56445, + stock: "2", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + retired: false + } + end + it 'is successful' do + user = User.create(user_hash) + user1 = User.create(second_user_hash) + cat = Category.create(name: "Cool Shit") + cat2 = Category.create(name: "Better Shit") + p = Product.create(product_hash) + p2 = Product.create(second_product) + user.products << [p, p2] + user1.products << [Product.create(third_product), Product.create(fourth_product)] + cat.products << [p, p2] + cat2.products << [p, p2] + get :index + expect(subject).to render_template :index + end + end +end diff --git a/spec/helpers/categories_helper_spec.rb b/spec/helpers/categories_helper_spec.rb new file mode 100644 index 0000000000..1035fad1e9 --- /dev/null +++ b/spec/helpers/categories_helper_spec.rb @@ -0,0 +1,12 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the CategoriesHelper. For example: +# +# describe CategoriesHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end diff --git a/spec/helpers/categoryproducts_helper_spec.rb b/spec/helpers/categoryproducts_helper_spec.rb new file mode 100644 index 0000000000..a792917af8 --- /dev/null +++ b/spec/helpers/categoryproducts_helper_spec.rb @@ -0,0 +1,12 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the CategoryproductsHelper. For example: +# +# describe CategoryproductsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end diff --git a/spec/helpers/orderitems_helper_spec.rb b/spec/helpers/orderitems_helper_spec.rb new file mode 100644 index 0000000000..c15e60eb55 --- /dev/null +++ b/spec/helpers/orderitems_helper_spec.rb @@ -0,0 +1,13 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the OrderitemsHelper. For example: +# +# describe OrderitemsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end + diff --git a/spec/helpers/orders_helper_spec.rb b/spec/helpers/orders_helper_spec.rb new file mode 100644 index 0000000000..492fe9f3d7 --- /dev/null +++ b/spec/helpers/orders_helper_spec.rb @@ -0,0 +1,12 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the OrdersHelper. For example: +# +# describe OrdersHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end diff --git a/spec/helpers/products_helper_spec.rb b/spec/helpers/products_helper_spec.rb new file mode 100644 index 0000000000..c60820c5cd --- /dev/null +++ b/spec/helpers/products_helper_spec.rb @@ -0,0 +1,12 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the ProductsHelper. For example: +# +# describe ProductsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end diff --git a/spec/helpers/reviews_helper_spec.rb b/spec/helpers/reviews_helper_spec.rb new file mode 100644 index 0000000000..85e4374e67 --- /dev/null +++ b/spec/helpers/reviews_helper_spec.rb @@ -0,0 +1,12 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the ReviewsHelper. For example: +# +# describe ReviewsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end diff --git a/spec/helpers/sessions_helper_spec.rb b/spec/helpers/sessions_helper_spec.rb new file mode 100644 index 0000000000..290e9d9cb5 --- /dev/null +++ b/spec/helpers/sessions_helper_spec.rb @@ -0,0 +1,12 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the SessionsHelper. For example: +# +# describe SessionsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb new file mode 100644 index 0000000000..48d28dd6f1 --- /dev/null +++ b/spec/helpers/users_helper_spec.rb @@ -0,0 +1,12 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the UsersHelper. For example: +# +# describe UsersHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end diff --git a/spec/helpers/welcome_helper_spec.rb b/spec/helpers/welcome_helper_spec.rb new file mode 100644 index 0000000000..f19c1c99d4 --- /dev/null +++ b/spec/helpers/welcome_helper_spec.rb @@ -0,0 +1,13 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the WelcomeHelper. For example: +# +# describe WelcomeHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end + diff --git a/spec/models/category_spec.rb b/spec/models/category_spec.rb new file mode 100644 index 0000000000..9a96f9d8ad --- /dev/null +++ b/spec/models/category_spec.rb @@ -0,0 +1,53 @@ +require 'rails_helper' + +RSpec.describe Category, type: :model do + + describe ".validates" do + it "must have a name" do + expect(Category.new(name: nil)).to_not be_valid + end + + it "must have a unique name" do + @test_category = Category.new(name: "Birthstone") + @test_category.save + expect(@test_category).to be_valid + expect(Category.new(name: "Birthstone")).to_not be_valid + @test_category.destroy + end + end + + describe "top(x)" do + let(:product_hash) do + {name: "Geometry Like Woahhh", + price: 5645245, + stock: "1", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + retired: false + } + end + let(:second_product) do + {name: "Another Product Thing", + price: 5645245, + stock: "2", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + retired: false + } + end + let(:category) do + category = Category.create(name: "Some Stuff") + p = Product.create(product_hash) + p2 = Product.create(second_product) + category.products << [p, p2] + return category + end + it "returns product instances" do + expect(category.top(2)[0]).to be_a(Product) + end + it "returns x products" do + expect(category.top(1).length).to eq(1) + expect(category.top(2).length).to eq(2) + end + end +end diff --git a/spec/models/order_spec.rb b/spec/models/order_spec.rb new file mode 100644 index 0000000000..c2538cc779 --- /dev/null +++ b/spec/models/order_spec.rb @@ -0,0 +1,246 @@ +require 'rails_helper' + +RSpec.describe Order, type: :model do + let(:good_hash) do + { + status: "pending", + cc_name: "John Carlisle", + email_address: "jcarl@gmail.com", + mailing_address: "653 Gorge Way", + cc_number: 5110538084994719, + cc_exp: "06/18", + cc_cvv: "674", + zip: 19583 + } + end + let(:product_hash) do + {name: "Geometry Like Woahhh", + price: 5645, + stock: "1", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + user_id: 2, + retired: false + } + end + let(:second_product) do + {name: "Another Product Thing", + price: 5645245, + stock: "2", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + user_id: 1, + retired: false + } + end + + describe ".validates" do + let (:no_status_hash) do + { + status: nil, + cc_name: "John Carlisle", + email_address: "jcarl@gmail.com", + mailing_address: "653 Gorge Way", + cc_number: 5110538084994719, + cc_exp: "06/18", + cc_cvv: "674", + zip: 19583 + } + end + # let (:no_name_hash) do + # { + # status: "pending", + # cc_name: nil, + # email_address: "jcarl@gmail.com", + # mailing_address: "653 Gorge Way", + # cc_number: 5110538084994719, + # cc_exp: "06/18", + # cc_cvv: "674", + # zip: 19583 + # } + # end + # + # let (:no_email_hash) do + # { + # status: "pending", + # cc_name: "John", + # email_address: nil, + # mailing_address: "653 Gorge Way", + # cc_number: 5110538084994719, + # cc_exp: "06/18", + # cc_cvv: "674", + # zip: 19583 + # } + # end + # + # let (:no_mailing_hash) do + # { + # status: "pending", + # cc_name: "John", + # email_address: "jcarl@gmail.com", + # mailing_address: nil, + # cc_number: 5110538084994719, + # cc_exp: "06/18", + # cc_cvv: "674", + # zip: 19583 + # } + # end + # + # let (:no_cc_num_hash) do + # { + # status: "pending", + # cc_name: "John", + # email_address: "jcarl@gmail.com", + # mailing_address: "123 Fake Street", + # cc_number: nil, + # cc_exp: "06/18", + # cc_cvv: "674", + # zip: 19583 + # } + # end + # + # let (:no_cc_exp_hash) do + # { + # status: "pending", + # cc_name: "John", + # email_address: "jcarl@gmail.com", + # mailing_address: "123 Fake Street", + # cc_number: 5110538084994719, + # cc_exp: nil, + # cc_cvv: "674", + # zip: 19583 + # } + # end + # + # let (:no_cc_cvv_hash) do + # { + # status: "pending", + # cc_name: "John", + # email_address: "jcarl@gmail.com", + # mailing_address: "123 Fake Street", + # cc_number: 5110538084994719, + # cc_exp: "06/18", + # cc_cvv: nil, + # zip: 19583 + # } + # end + # + # let (:no_zip_hash) do + # { + # status: "pending", + # cc_name: "John", + # email_address: "jcarl@gmail.com", + # mailing_address: "123 Fake Street", + # cc_number: 5110538084994719, + # cc_exp: "06/18", + # cc_cvv: "123", + # zip: nil + # } + # end + + it "must have a status" do + expect(Order.new(no_status_hash)).to_not be_valid + expect(Order.new(good_hash)).to be_valid + end + # + # it "must have a credit card name on pay" do + # expect(Order.new(no_name_hash)).to_not be_valid + # end + + # it "must have an email address on pay" do + # expect(Order.new(no_email_hash)).to_not be_valid + # end + # + # it "must have a mailing address on pay" do + # expect(Order.new(no_mailing_hash)).to_not be_valid + # end + # + # it "must have a credit card num on pay" do + # expect(Order.new(no_cc_num_hash)).to_not be_valid + # end + + # it "must have a credit card expiration date on pay" do + # expect(Order.new(no_cc_exp_hash)).to_not be_valid + # end + # + # it "must have a credit card cvv on pay" do + # expect(Order.new(no_cc_cvv_hash)).to_not be_valid + # end + # + # it "must have a zip code on pay" do + # expect(Order.new(no_zip_hash)).to_not be_valid + # end + + # it "must have an order item on creation" do + # t.integer "product_id" + # t.integer "order_id" + # t.integer "quantity" + # @order = Order.new + # @test_order_item = Orderitem.create(product_id: 1, order_id: @) + # end + end + + describe "self.pending" do + it "" do + + end + end + + describe "decrement_products_stock" do + it "" do + + end + end + + describe "total" do + it "" do + + end + end + + describe "total_by_user(user_id)" do + let (:order) do + order = Order.create(good_hash) + p = Product.create!(product_hash) + p2 = Product.create!(second_product) + order.products << [p, p2] + return order + end + it "returns an integer" do + expect(order.total_by_user(1)).to be_a(Integer) + end + it "returns the total sales for a given user" do + expect(order.total_by_user(2)).to eq(5645) + expect(order.total_by_user(1)).to eq(5645245) + end + end + + describe "mark_shipped?" do + before :each do + p = Product.create!(product_hash) + p2 = Product.create!(second_product) + @order = Order.pending(p) + @order.products << p2 + @order.orderitems[0].item_shipped + @order.mark_shipped + + @order2 = Order.pending(p) + @order2.products << [p2] + # @order2.update(good_hash) + @order2.orderitems[0].item_shipped + @order2.orderitems[1].item_shipped + @order2.mark_shipped + end + it "marks an order as shipped only if all orderitems are shipped" do + expect(@order.status).to eq("pending") + expect(@order2.status).to eq("completed") + end + end + + #describe "session_over" do + #it "" + #end + + #test that destroying an order destroys its order items + +end diff --git a/spec/models/orderitem_spec.rb b/spec/models/orderitem_spec.rb new file mode 100644 index 0000000000..63f198bccf --- /dev/null +++ b/spec/models/orderitem_spec.rb @@ -0,0 +1 @@ +require 'rails_helper' diff --git a/spec/models/product_spec.rb b/spec/models/product_spec.rb new file mode 100644 index 0000000000..7b6719392b --- /dev/null +++ b/spec/models/product_spec.rb @@ -0,0 +1,218 @@ +require 'rails_helper' +require 'pry' + +RSpec.describe Product, type: :model do + let(:good_hash) do + {name: "Geometry Like Woah", + price: 5645245, + user_id: "2", + stock: "1", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + retired: false + } + end + let(:second_hash) do + {name: "Geometry 4", + price: 5645245, + user_id: "4", + stock: "1", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + retired: false + } + end + let(:third_hash) do + {name: "Geometry 3", + price: 5645245, + user_id: "3", + stock: "1", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + retired: false + } + end + + describe ".validates" do + + let (:no_name_hash) do + {name: nil, + price: 5645245, + user_id: "2", + stock: "1", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you." + } + end + + let (:no_price_hash) do + { + name: "Harry", + price: nil, + user_id: "2", + stock: "1", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you." + } + end + + let (:price_of_zero) do + { + name: "Harry", + price: 0, + user_id: "2", + stock: "1", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you." + } + end + + let (:price_not_a_number) do + { + name: "Harry", + price: "two dollars", + user_id: "2", + stock: "1", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you." + } + end + + let (:no_user_id_hash) do + { + name: "Harry", + price: 435345, + user_id: nil, + stock: "1", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you." + } + end + + let (:stock_of_negative) do + { + name: "Harry", + price: 435345, + user_id: "2", + stock: -1, + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you." + } + end + + let (:retired) do + { + name: "Harry", + price: 435345, + user_id: "2", + stock: 0, + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + retired: true + } + end + + let (:not_retired) do + { + name: "Harry", + price: 435345, + user_id: "2", + stock: 0, + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + retired: false + } + end + + it "must have a name" do + expect(Product.new(good_hash)).to be_valid + expect(Product.new(no_name_hash)).to_not be_valid + end +# + it "must have a unique name" do + @test_product = Product.new(good_hash) + @test_product.save + expect(@test_product).to be_valid + expect(Product.new(good_hash)).to_not be_valid + @test_product.destroy + end + + it "must have a price" do + expect(Product.new(no_price_hash)).to_not be_valid + end + + it "must have a price that is a number" do + expect(Product.new(price_not_a_number)).to_not be_valid + end + + it "must have a price greater than zero" do + expect(Product.new(price_of_zero)).to_not be_valid + end + + it "has a stock that isn't negative" do + expect(Product.new(stock_of_negative)).to_not be_valid + end + + # it "must belong to a User" do + # expect(Product.new(no_user_id_hash)).to_not be_valid + # end + + # it "upon creation is not retired" do + # expect(Product.new(retired)).to_not be_valid + # expect(Product.new(not_retired)).to be_valid + # end + + it "is retired with (insert method here to test?)" do + end + + #test that destroying a product destroys its reviews + + end + + describe "belongs_to_user?" do + it "" do + + end + end + + describe "avg_rating" do + let (:product) do + product = Product.create(good_hash) + r1 = Review.create(rating: 1, product_id: product.id) + r2 = Review.create(rating: 5, product_id: product.id) + product.reviews << [r1, r2] + return product + end + + it "returns an integer" do + expect(product.avg_rating).to be_a(Integer) + end + + it "returns average of all ratings of product reviews" do + expect(product.avg_rating).to eq(3) + end + + it "returns zero if product has no reviews" do + expect(Product.create(good_hash).avg_rating).to eq(0) + end + + end + + describe "self.top_selling(product_array, x)" do + let(:p) do + p = [] + p << Product.create(good_hash) + p << Product.create(second_hash) + p << Product.create(third_hash) + return p + end + it "returns Product instances" do + expect(Product.top_selling(p, 2)[0]).to be_a(Product) + end + it "returns x number of instances" do + expect(Product.top_selling(p, 2).length).to eq(2) + expect(Product.top_selling(p, 1).length).to eq(1) + end + end + +end diff --git a/spec/models/review_spec.rb b/spec/models/review_spec.rb new file mode 100644 index 0000000000..4f2b116af8 --- /dev/null +++ b/spec/models/review_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Review, type: :model do + +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb new file mode 100644 index 0000000000..e6b73db5bd --- /dev/null +++ b/spec/models/user_spec.rb @@ -0,0 +1,221 @@ +require 'rails_helper' + +RSpec.describe User, type: :model do + let(:good_hash) do { + username: "Burp", + email_address: "thing@thing.com", + password: "this", + password_confirmation: "this" + } + end + let(:product_hash) do + {name: "Geometry Like Woah", + price: 20, + stock: "1", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + retired: "false" + } + end + let(:second_product) do + {name: "Another Nother Product", + price: 25, + stock: "2", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + retired: "false" + } + end + let(:third_product) do + {name: "Another Product", + price: 50, + stock: "2", + photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDeCvOq-lfd-xau5kCj_RZ5WOD1wldXJybYd9abKVYwZKaGAay", + description: "I drew this just for you.", + user_id: 15, + retired: "false" + } + end + # create a let for some some orders + describe "orders" do + let(:user) do + user = User.create(good_hash) + p = Product.create!(product_hash) + p2 = Product.create!(second_product) + p3 = Product.create!(third_product) + user.products << [p, p2] + order = Order.pending(p) + order2 = Order.pending(p2) + order3 = Order.pending(p3) + return user + end + it "returns an array of order instances" do + expect(user.orders).to be_a(Array) + expect(user.orders[0]).to be_a(Order) + end + it "only returns orders a user has orderitems in" do + expect(user.orders.length).to eq(2) + expect(Order.all.length).to eq(3) + end + end + + describe "orders_by_status" do + let(:paid_order) do { + status: "paid", + cc_name: "Kelly Phelly", + email_address: "kelly@kellkell.com", + mailing_address: "848 Magpie Lane", + cc_number: 340727812705850, + cc_exp: "03/11", + cc_cvv: "454", + zip: 94983, + placed_at: rand(1.year.ago..Time.now) + } + end + let(:user) do + user = User.create(good_hash) + p = Product.create!(product_hash) + p2 = Product.create!(second_product) + p3 = Product.create!(third_product) + user.products << [p, p2, p3] + order = Order.pending(p) + order2 = Order.pending(p2) + order3 = Order.pending(p3) + order2.update(paid_order) + order2.save + return user + end + it "returns user orders with given status" do + expect(user.orders_by_status("paid").length).to eq(1) + expect(user.orders_by_status("pending").length).to eq(2) + end + end + + + describe "top(x)" do + let(:user) do + user = User.create(good_hash) + p = Product.create!(product_hash) + p2 = Product.create!(second_product) + user.products << [p, p2] + return user + end + it "returns product instances" do + expect(user.top(2)[0]).to be_a(Product) + end + it "returns x products" do + expect(user.top(1).length).to eq(1) + expect(user.top(2).length).to eq(2) + end + end + + describe "revenue" do + let(:user) do + user = User.create(good_hash) + p = Product.create!(product_hash) + p2 = Product.create!(second_product) + p3 = Product.create!(third_product) + user.products << [p, p2] + order = Order.pending(p) + order2 = Order.pending(p2) + order3 = Order.pending(p3) + return user + end + # create an order + it "returns an integer" do + expect(user.revenue).to be_a(Integer) + end + it "returns total of all products that have been orderitems" do + expect(user.revenue).to eq(45) + end + end + + describe "rev_by_status" do + let(:paid_order) do { + status: "paid", + cc_name: "Kelly Phelly", + email_address: "kelly@kellkell.com", + mailing_address: "848 Magpie Lane", + cc_number: 340727812705850, + cc_exp: "03/11", + cc_cvv: "454", + zip: 94983, + placed_at: rand(1.year.ago..Time.now) + } + end + let(:user) do + user = User.create(good_hash) + p = Product.create!(product_hash) + p2 = Product.create!(second_product) + user.products << [p, p2] + order = Order.pending(p) + order2 = Order.pending(p2) + order2.update(paid_order) + order2.save + return user + end + #create orders of various statuses + it "returns an integer" do + expect(user.rev_by_status('pending')).to be_a(Integer) + end + it "returns total sales of products from orders with given status" do + expect(user.rev_by_status('pending')).to eq(20) + expect(user.rev_by_status('paid')).to eq(25) + end + end + + describe "orderitems" do + let(:user) do + user = User.create(good_hash) + p = Product.create!(product_hash) + p2 = Product.create!(second_product) + p3 = Product.create!(third_product) + user.products << [p, p2] + order = Order.pending(p) + order2 = Order.pending(p2) + order3 = Order.pending(p3) + return user + end + + it "returns an array" do + expect(user.orderitems.class).to eq Array + end + + it "contains Orderitems" do + expect(user.orderitems[0]).to be_a Orderitem + expect(user.orderitems[1]).to be_a Orderitem + end + + it "returns orderitems associated with user" do + expect(user.orderitems.length).to eq 2 + end + end + + describe "orderitems_by_order" do + let(:user) do + user = User.create(good_hash) + p = Product.create!(product_hash) + p2 = Product.create!(second_product) + p3 = Product.create!(third_product) + user.products << [p, p2] + order = Order.pending(p) + order2 = Order.pending(p2) + order3 = Order.pending(p3) + return user + end + + it "returns an array" do + expect(user.orderitems.class).to eq Array + end + + it "contains Orderitems" do + expect(user.orderitems[0]).to be_a Orderitem + expect(user.orderitems[1]).to be_a Orderitem + + end + + it "returns orderitems associated with an order" do + expect(user.orders.length).to eq 2 + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 13cf12afe8..0f01fe3d56 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -37,6 +37,9 @@ expectations.include_chain_clauses_in_custom_matcher_descriptions = true end + config.alias_example_to :fit, focused: true + config.filter_run focused: true + config.run_all_when_everything_filtered = true # rspec-mocks config goes here. You can use an alternate test double # library (such as bogus or mocha) by changing the `mock_with` option here. config.mock_with :rspec do |mocks| diff --git a/spec/support/app_controller.rb b/spec/support/app_controller.rb new file mode 100644 index 0000000000..d3af4052f7 --- /dev/null +++ b/spec/support/app_controller.rb @@ -0,0 +1,12 @@ +require 'rails_helper' + +RSpec.shared_examples "a quartzy controller" do + + describe 'GET index' do + it 'is successful' do + get :index + expect(subject.response.status).to eq(200) + end + end + +end \ No newline at end of file