GithubHelp home page GithubHelp logo

little_shop's Introduction

Little Shop of Orders

The Waddams Emporium

  • David Davydov
  • Jesse Spevack
  • Sonia Gupta
  • Susi Irwin

Production: https://waddams-emporium.herokuapp.com/


Introduction

This project is a Ruby on Rails Web Application which has been designed and biult as an online commerce platform to facilitate online ordering.

The Waddams Emporium is an online e-commerce emporium specializing in artisinal, hand-crafted office accoutrements. Users can be either a Logged-In customer or a Visitor and the site is run by an Administrator account. This administrator can log in, add and remove items, and monitor orders.

We have used a gem called Paperclip to handle the images on the site. It connects to the Amazon AWS. We have also implemented Product Reviews where a logged-in user can add and delete his/her own review and a visitor can read all reviews.

Learning Goals

  • Use TDD to drive all layers of Rails development including unit and integration tests
  • Design a system of models which use one-to-one, one-to-many, and many-to-many relationships
  • Practice mixing HTML, CSS, and templates to create an inviting and usable User Interface
  • Differentiate responsibilities between components of the Rails stack
  • Build a logical user-flow that moves across multiple controllers and models
  • Practice an agile workflow and improve communication skills working within a team

Restrictions

Project implementation may not use:

  • Any external library for authentication except bcrypt

Application Details

  • Ruby version: 4

  • Configuration:

    • Run bundle install
  • Database creation, initialization, and seeding:

    • rake db:create db:migrate db:seed
  • How to run the test suite

    • rspec

little_shop's People

Contributors

jesse-spevack avatar susiirwin avatar kctrlv avatar

Watchers

 avatar  avatar  avatar

Forkers

susiirwin

little_shop's Issues

Visitor Creates an Account

As a visitor
When I visit "/login
And when I click link "Create Account"
And I fill in my desired credentials
And I submit my information
Then my current page should be "/dashboard"
And I should see a message in the navbar that says "Logged in as SOME_USER"
And I should see my profile information
And I should not see a link for "Login"
And I should see a link for "Logout"

controller/dashboard_controller.rb

class DashboardsController < ApplicationController
  def show
    @user = User.find(session[:user_id])
  end
end

I propose we add authorization to this controller. We should require that there be a current_user. Since the order controller requires a current_user as well, we should add a require_user helper method to the controller/base_controller.rb.

Unauthenticated users security

Background: An unauthenticated user and their abilities

  As an Unauthenticated User
  I cannot view another user's private data, such as current order, etc.
  I should be redirected to login/create account when I try to check out.
  I cannot view the administrator screens or use administrator functionality.
  I cannot make myself an administrator.

Admin User Dashboard

As an Admin
When I visit "/admin/dashboard"
I will see a heading on the page that says "Admin Dashboard"

  As a registered user
  When I visit "/admin/dashboard"
  I get a 404

  As an unregistered user
  When I visit "/admin/dashboard"
  I get a 404

Authenticated users security

Background: An authenticated user

  As an Authenticated User
  I cannot view another user's private data (current or past orders, etc)
  I cannot view the administrator screens or use admin functionality
  I cannot make myself an admin

Adjusting the quantity of an item in the cart

Background: My cart has an item in it

  As a visitor
  When I visit "/cart"
  Then I should see my item with a quantity of 1
  And when I increase the quantity
  Then my current page should be '/cart'
  And that item's quantity should reflect the increase
  And the subtotal for that item should increase
  And the total for the cart should match that increase
  And when I decrease the quantity
  Then my current page should be '/cart'
  And that item's quantity should reflect the decrease
  And the subtotal for that item should decrease
  And the total for the cart should match that decrease

Viewing a past order

Background: An existing user that has one previous order

  As an authenticated user
  When I visit "/orders"
  Then I should see my past order
  And I should see a link to view that order
  And when I click that link
  Then I should see each item that was order with the quantity and line-item subtotals
  And I should see links to each item's show page
  And I should see the current status of the order **(ordered, paid, cancelled, completed)**
  And I should see the total price for the order
  And I should see the date/time that the order was submitted
  If the order was completed or cancelled
  Then I should see a timestamp when the action took place

Removing an item from my cart

Background: My cart has an item in it

  As a visitor
  When I visit "/cart"
  And I click link "Remove"
  Then my current page should be "/cart"
  And I should see a message styled in green
  And the message should say "Successfully removed SOME_ITEM from your cart."
  And the title "SOME_ITEM" should be a link to that item in case the user wants to add it back
  And I should not see the item listed in cart

controllers/orders_controller.rb - refactor

class OrdersController < ApplicationController
  before_action :require_user

  def require_user
    redirect_to login_path if !logged_in?
  end

  def index
    @orders = current_user.orders
  end

  def create
    @cart = session[:cart]
    @user = current_user
    order_compiler = OrderCompiler.new(@cart, @user)
    order_compiler.populated_item_order
    flash[:success] = "Order was successfully placed."
    redirect_to orders_path
  end

  def show
    @order = Order.find(params[:id])
    @items = @order.items
  end
end

The require_user should be extracted to the controllers/base_controller.rb

I propose the following change to the create method, which would necessitate some change to the OrderComplier class.

def create
  status = OrderCompiler.new(session[:cart], current_user).compile
  flash[:success] = "Order was successfully placed." if status
  redirect_to orders_path
end

Admin views an individual Order

As an authenticated Admin, when I visit an individual order page
Then I can see the order's date and time.
And I can see the purchaser's full name and address.
And I can see, for each item on the order:
- The item's name, which is linked to the item page.
- Quantity in this order.
- Price
- Line item subtotal.
And I can see the total for the order.
And I can see the status for the order.

Visitor can view items

Background: I have several items and each of them has a title, description, price, and image

  As a visitor
  When I visit "/items"
  I can see all existing items

controllers/session_controller.rb - refactor

class SessionsController < ApplicationController
  def new
  end

  def create
    @user = User.find_by(username: params[:session][:username])
    if @user && @user.authenticate(params[:session][:password])
      session[:user_id] = @user.id
      if @user.admin?
        redirect_to admin_dashboard_path
      elsif @user.user?
        redirect_to dashboard_path
      end
    else
      redirect_to login_path
    end
  end

  def destroy
    session.clear
    redirect_to items_path
  end
end

I think we should extract the nested conditional into a private method. We also don't need an instance variable unless we are rendering a new view, right? I propose something like:

def create
  user = User.find_by(username: params[:session][:username])
  if user && user.authenticate(params[:session][:password])
    session[:user_id] = user.id
    redirect(user)
  else
    redirect_to login_path
  end
end


def redirect(user)
  if user.admin?
    redirect_to admin_dashboard_path
  elsif user.user?
    redirect_to dashboard_path
  end
end

Adding items to the cart

Background: Items, and a user that is not logged in

  As a visitor
  When I visit any page with an item on it
  I should see a link or button for "Add to Cart"
  When I click "Add to cart" for that item
  And I click a link or button to view cart
  And my current path should be "/cart"
  And I should see a small image, title, description and price for the item I just added
  And there should be a "total" price for the cart that should be the sum of all items in the cart

Checking out

Background: An existing user and a cart with items

  As a visitor
  When I add items to my cart
  And I visit "/cart"
  And I click "Login or Register to Checkout"
  Then I should be required to login
  When I am logged in
  And I visit my cart
  And when I click "Checkout"
  Then the order should be placed
  And my current page should be "/orders"
  And I should see a message "Order was successfully placed"
  And I should see the order I just placed in a table

Admin Orders

As an Admin
When I visit the dashboard
Then I can see a listing of all orders
And I can see the total number of orders for each status ("Ordered", "Paid", "Cancelled", "Completed")
And I can see a link for each individual order
And I can filter orders to display by each status type ("Ordered", "Paid", "Cancelled", "Completed")
And I have links to transition between statuses
- I can click on "cancel" on individual orders which are "paid" or "ordered"
- I can click on "mark as paid" on orders that are "ordered"
- I can click on "mark as completed" on orders that are "paid"

Retired Items

As a user if I visit an item page and that item has been retired
Then I should still be able to access the item page
And I should not be able to add the item to their cart
And I should see in place of the "Add to Cart" button or link - "Item Retired"

Viewing past orders

Background: An existing user that has multiple orders

  As an Authenticated User
  When I visit "/orders"
  Then I should see all orders belonging to me and no other orders

Browsing Items by category

Background: I have two categories with titles and each has two different items assigned

  As a visitor
  When I visit "/:CATEGORY_NAME"
  I see all items assigned to that category

Guest User With Items

As a visitor when I have items in my cart
And when I visit "/cart"
I should not see an option to "Checkout"
I should see an option to "Login or Create Account to Checkout"
After I create an account
And I visit "/cart
Then I should see all of the data that was there when I was not logged in

Check that test database behaves properly

When building the remove item test, we noticed that the id of an item was at 6 rather than the expected 1. I remember that the database will continue to autoincrement the object id when it is emptied out rather than dropped altogether, but just want to ensure that this is what we want.

Create Wireframes

Think about what you think the workflow should be on the site. Which of those views is most important?

In addition to the home page wireframe, create wireframes the page immediately following your Log In and the next most important page for your application.

  Examples might be: A users' profile page, a product page, an admin dashboard etc...

Logging Out

As a logged in user
When I click "Logout"
Then I should see see "Login"
And I should not see "Logout"

Authenticated User Logging In

As a visitor
When I visit "/"
Then I should see a link for "Login"
And when I click "Login"
And I should be on the "/login" page
I should see a place to insert my credentials to login
And I should see a link to "Create Account"

Admin logs in

As an Admin
When I log in
Then I am redirected to "/admin/dashboard"

login or create account to checkout

Currently we have the following in our items.html.erb:

<% unless logged_in? %> <%= link_to "Login or Create Account to Checkout", login_path %> <% end %>

I think that belongs in the nav bar.

controller/carts_controller.rb - refactor

    item = Item.find(params[:item_id])
    @cart.add_item(item.id)

session[:cart] = @cart.contents
redirect_to items_path


  end```

I think the first line is not necessary since we never call item in the remainder of the method. We can just give the `add_item` method the `params[:item_id]` as its input.

The only reason to keep it would be if we added a flash message saying "Successfully added item.title to cart!" as we do with the `destroy` method.

`def edit
  # {"_method"=>"put", "change_quantity"=>"increase", "item_id"=>"6", "controller"=>"carts", "action"
    item = Item.find(params[:item_id])
    if params[:change_quantity] == 'increase'
      @cart.increase_quantity(item.id)
    elsif params[:change_quantity] == 'decrease'
      @cart.decrease_quantity(item.id)
    end
    redirect_to cart_path
  end`

I prefer predicate methods in conditionals because I think they are more readable and I've gotten that feedback from Mike Dao a few times in project evaluations. I would propose creating a private method such as `user_clicked_increase?` and `user_clicked_decrease?`.

Last point, we have some commented out lines in this file that we should remove before we merge to master.

Admin cannot modify users

As a logged in Admin
I can modify my account data
But I cannot modify any other user's account data

This is a test issue

Will this show up on waffle and thus allow me to create cards only in github.cm?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.