From: Ira W. Snyder Date: Fri, 23 Nov 2007 06:32:31 +0000 (-0800) Subject: Add Purchase system X-Git-Tag: turned-in~57 X-Git-Url: https://irasnyder.com/gitweb/?a=commitdiff_plain;ds=sidebyside;h=ebb2b4d40713d535c06970b2a17aace4458ecf25;hp=51e5c301fa78679232f16b450632fc890c02c4f2;p=cs356-p2-videostore.git Add Purchase system Signed-off-by: Ira W. Snyder --- diff --git a/app/controllers/purchase_controller.rb b/app/controllers/purchase_controller.rb new file mode 100644 index 0000000..1516498 --- /dev/null +++ b/app/controllers/purchase_controller.rb @@ -0,0 +1,109 @@ +class PurchaseController < ApplicationController + + def index + redirect_to :action => :begin + end + + def list + @purchase_pages, @purchase = paginate :purchases, :per_page => 100 + end + + def begin + # enter a customer id here + render :action => 'begin' + session[:total] = 0.00 + end + + def customer_ok + if Customer.find_by_id(params[:customer_id]) + session[:customer_id] = params[:customer_id] + redirect_to :action => :menu + else + flash[:error] = "Customer ID is invalid" + redirect_to :action => :begin + end + end + + def menu + @customer = Customer.find_by_id(session[:customer_id]) + @total_price = session[:total] + render :action => 'menu' + end + + def rent_begin + render :action => 'rent_begin' + end + + def rent_validate + @customer = Customer.find_by_id(session[:customer_id]) + @rentable = Rentable.find_by_id(params[:rentable_id]) + + if @customer.nil? + flash[:error] = "Customer ID is invalid" + redirect_to :action => :begin + return + end + + if @rentable.nil? + flash[:error] = "Rentable ID is invalid" + redirect_to :action => :rent_begin + return + end + + # Actually record the purchase + purchase = RentablePurchase.new + purchase.customer_id = session[:customer_id] + purchase.date = Time.now.to_date + purchase.price = @rentable.calculated_price + session[:total] += @rentable.calculated_price + purchase.rentable = @rentable + purchase.save! + + flash[:notice] = "Successfully made purchase" + redirect_to :action => :menu + end + + def buy_begin + render :action => 'buy_begin' + end + + def buy_validate + @customer = Customer.find_by_id(session[:customer_id]) + @merchandise = Merchandise.find_by_id(params[:merchandise_id]) + + if @customer.nil? + flash[:error] = "Customer ID is invalid" + redirect_to :action => :begin + return + end + + if @merchandise.nil? + flash[:error] = "Merchandise ID is invalid" + redirect_to :action => :buy_begin + return + end + + if @merchandise.quantity < 1 + flash[:error] = "The system thinks we are out of this merchandise item!" + redirect_to :action => :buy_begin + return + end + + # Actually record the purchase + purchase = MerchandisePurchase.new + purchase.customer_id = session[:customer_id] + purchase.date = Time.now.to_date + purchase.price = @merchandise.price + session[:total] += @merchandise.price + purchase.merchandise = @merchandise + purchase.quantity = 1 + @merchandise.quantity -= 1 + + # Save both the merchandise (we changed the quantity) and the purchase to the log + @merchandise.save! + purchase.save! + + flash[:notice] = "Successfully made purchase" + redirect_to :action => :menu + end +end diff --git a/app/helpers/purchase_helper.rb b/app/helpers/purchase_helper.rb new file mode 100644 index 0000000..f8a3a64 --- /dev/null +++ b/app/helpers/purchase_helper.rb @@ -0,0 +1,2 @@ +module PurchaseHelper +end diff --git a/app/models/customer.rb b/app/models/customer.rb index 901b9a5..aba5044 100644 --- a/app/models/customer.rb +++ b/app/models/customer.rb @@ -1,6 +1,8 @@ class Customer < ActiveRecord::Base has_many :coitems has_many :bitems + has_many :merchandise_purchases + has_many :rentable_purchases validates_presence_of :name, :email, :phone, :address validates_numericality_of :debt diff --git a/app/models/game.rb b/app/models/game.rb index 0ca782b..efdb260 100644 --- a/app/models/game.rb +++ b/app/models/game.rb @@ -2,4 +2,8 @@ class Game < Rentable validates_presence_of :game_genre validates_presence_of :platform + def calculated_price + # FIXME: generate this based on day of week, newrelase + return 11 + end end diff --git a/app/models/merchandise.rb b/app/models/merchandise.rb index 463cfd3..16fd1e8 100644 --- a/app/models/merchandise.rb +++ b/app/models/merchandise.rb @@ -1,4 +1,6 @@ class Merchandise < ActiveRecord::Base + has_many :merchandise_purchases + validates_presence_of :name validates_numericality_of :quantity validates_numericality_of :price diff --git a/app/models/merchandise_purchase.rb b/app/models/merchandise_purchase.rb new file mode 100644 index 0000000..94bf758 --- /dev/null +++ b/app/models/merchandise_purchase.rb @@ -0,0 +1,16 @@ +class MerchandisePurchase < Purchase + belongs_to :merchandise + belongs_to :customer + + validates_presence_of :merchandise_id + validates_presence_of :quantity + + validates_numericality_of :merchandise_id + validates_numericality_of :quantity + + protected + def validate + errors.add(:merchandise_id, "does not exist in the database") if merchandise.nil? + #errors.add(:quantity, "must be 1 or greater") if quantity < 1 + end +end diff --git a/app/models/purchase.rb b/app/models/purchase.rb index e688f99..ff07e41 100644 --- a/app/models/purchase.rb +++ b/app/models/purchase.rb @@ -1,2 +1,15 @@ class Purchase < ActiveRecord::Base + belongs_to :customer + + validates_presence_of :customer_id + validates_presence_of :date + validates_presence_of :price + validates_numericality_of :price + + protected + def validate + errors.add(:price, "cannot be negative") if price < 0 + errors.add(:price, "cannot be less than $0.01") if price < 0.01 + errors.add(:customer_id, "does not exist in the database") if customer.nil? + end end diff --git a/app/models/rentable.rb b/app/models/rentable.rb index 69ca422..e52af25 100644 --- a/app/models/rentable.rb +++ b/app/models/rentable.rb @@ -1,5 +1,6 @@ class Rentable < ActiveRecord::Base - has_many :coitem + has_many :coitems + has_many :rentable_purchases validates_presence_of :title # don't validate newrelease, false is ok diff --git a/app/models/rentable_purchase.rb b/app/models/rentable_purchase.rb new file mode 100644 index 0000000..77b8233 --- /dev/null +++ b/app/models/rentable_purchase.rb @@ -0,0 +1,12 @@ +class RentablePurchase < Purchase + belongs_to :rentable + belongs_to :customer + + validates_presence_of :rentable_id + validates_numericality_of :rentable_id + + protected + def validate + errors.add(:rentable_id, "is not in the database") if rentable.nil? + end +end diff --git a/app/models/video.rb b/app/models/video.rb index 411c978..fdf90c3 100644 --- a/app/models/video.rb +++ b/app/models/video.rb @@ -6,6 +6,11 @@ class Video < Rentable validates_presence_of :video_genre validates_presence_of :media + def calculated_price + # FIXME: generate this based on day of week, newrelase + return 11 + end + protected def validate errors.add(:video_genre, "does not exist in the database") if video_genre.nil? diff --git a/app/views/layouts/purchase.rhtml b/app/views/layouts/purchase.rhtml new file mode 100644 index 0000000..26387b8 --- /dev/null +++ b/app/views/layouts/purchase.rhtml @@ -0,0 +1,18 @@ + + + + + + Bitem: <%= controller.action_name %> + <%= stylesheet_link_tag 'scaffold' %> + + + +

<%= flash[:notice] %>

+

<%= flash[:error] %>

+ +<%= yield %> + + + diff --git a/app/views/purchase/begin.rhtml b/app/views/purchase/begin.rhtml new file mode 100644 index 0000000..b108db7 --- /dev/null +++ b/app/views/purchase/begin.rhtml @@ -0,0 +1,10 @@ +

Start a Purchase

+ +

Please read the customer's ID number off of their card and enter +it in the box below.

+ +<%= start_form_tag :action => 'customer_ok'%> +<%= text_field 'customer_id', nil %> + <%= submit_tag 'Ok' %> +<%= end_form_tag %> + diff --git a/app/views/purchase/buy.rhtml b/app/views/purchase/buy.rhtml new file mode 100644 index 0000000..61c6d0f --- /dev/null +++ b/app/views/purchase/buy.rhtml @@ -0,0 +1,2 @@ +

Purchase#buy

+

Find me in app/views/purchase/buy.rhtml

diff --git a/app/views/purchase/buy_begin.rhtml b/app/views/purchase/buy_begin.rhtml new file mode 100644 index 0000000..7ea2912 --- /dev/null +++ b/app/views/purchase/buy_begin.rhtml @@ -0,0 +1,11 @@ +

Purchase some Merchandise

+ +

Please read the item's ID number off of the bar code, and type it into +the box below.

+ +<%= start_form_tag :action => 'buy_validate'%> +<%= text_field 'merchandise_id', nil %> + <%= submit_tag 'Ok' %> +<%= end_form_tag %> + + diff --git a/app/views/purchase/list.rhtml b/app/views/purchase/list.rhtml new file mode 100644 index 0000000..593b7a6 --- /dev/null +++ b/app/views/purchase/list.rhtml @@ -0,0 +1,27 @@ +

Listing purchases

+ + + + <% for column in Purchase.content_columns %> + + <% end %> + + +<% for purchase in @purchases %> + + <% for column in Purchase.content_columns %> + + <% end %> + + + + +<% end %> +
<%= column.human_name %>
<%=h purchase.send(column.name) %><%= link_to 'Show', :action => 'show', :id => purchase %><%= link_to 'Edit', :action => 'edit', :id => purchase %><%= link_to 'Destroy', { :action => 'destroy', :id => purchase }, :confirm => 'Are you sure?', :method => :post %>
+ +<%= link_to 'Previous page', { :page => @purchase_pages.current.previous } if @purchase_pages.current.previous %> +<%= link_to 'Next page', { :page => @purchase_pages.current.next } if @purchase_pages.current.next %> + +
+ +<%= link_to 'New purchase', :action => 'new' %> diff --git a/app/views/purchase/menu.rhtml b/app/views/purchase/menu.rhtml new file mode 100644 index 0000000..ce8a646 --- /dev/null +++ b/app/views/purchase/menu.rhtml @@ -0,0 +1,14 @@ +

Purchase Menu

+ + + + + +<%=link_to 'End Purchase', :action => 'index' %> diff --git a/app/views/purchase/rent.rhtml b/app/views/purchase/rent.rhtml new file mode 100644 index 0000000..076d2be --- /dev/null +++ b/app/views/purchase/rent.rhtml @@ -0,0 +1,2 @@ +

Purchase#rent

+

Find me in app/views/purchase/rent.rhtml

diff --git a/app/views/purchase/rent_begin.rhtml b/app/views/purchase/rent_begin.rhtml new file mode 100644 index 0000000..f69769a --- /dev/null +++ b/app/views/purchase/rent_begin.rhtml @@ -0,0 +1,10 @@ +

Check out a Rentable Item

+ +

Please read the item's ID number off of the bar code, and type it into +the box below.

+ +<%= start_form_tag :action => 'rent_validate'%> +<%= text_field 'rentable_id', nil %> + <%= submit_tag 'Ok' %> +<%= end_form_tag %> + diff --git a/db/development.sqlite3 b/db/development.sqlite3 index b02e912..3f10e53 100644 Binary files a/db/development.sqlite3 and b/db/development.sqlite3 differ diff --git a/db/migrate/017_create_rentable_purchases.rb b/db/migrate/017_create_rentable_purchases.rb new file mode 100644 index 0000000..9d6f312 --- /dev/null +++ b/db/migrate/017_create_rentable_purchases.rb @@ -0,0 +1,7 @@ +class CreateRentablePurchases < ActiveRecord::Migration + def self.up + end + + def self.down + end +end diff --git a/db/migrate/018_create_merchandise_purchases.rb b/db/migrate/018_create_merchandise_purchases.rb new file mode 100644 index 0000000..4acf566 --- /dev/null +++ b/db/migrate/018_create_merchandise_purchases.rb @@ -0,0 +1,7 @@ +class CreateMerchandisePurchases < ActiveRecord::Migration + def self.up + end + + def self.down + end +end diff --git a/db/migrate/019_remove_purchase_due_date.rb b/db/migrate/019_remove_purchase_due_date.rb new file mode 100644 index 0000000..a917da9 --- /dev/null +++ b/db/migrate/019_remove_purchase_due_date.rb @@ -0,0 +1,9 @@ +class RemovePurchaseDueDate < ActiveRecord::Migration + def self.up + remove_column :purchases, :due_date + end + + def self.down + add_column :purchases, :due_date, :date + end +end diff --git a/db/schema.rb b/db/schema.rb index 212ac71..2e0f138 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -2,7 +2,7 @@ # migrations feature of ActiveRecord to incrementally modify your database, and # then regenerate this schema definition. -ActiveRecord::Schema.define(:version => 16) do +ActiveRecord::Schema.define(:version => 19) do create_table "bitems", :force => true do |t| t.column "customer_id", :integer, :null => false @@ -29,6 +29,9 @@ ActiveRecord::Schema.define(:version => 16) do t.column "name", :string, :null => false end + create_table "merchandise_purchases", :force => true do |t| + end + create_table "merchandises", :force => true do |t| t.column "name", :string, :null => false t.column "quantity", :integer, :default => 0, :null => false @@ -39,9 +42,8 @@ ActiveRecord::Schema.define(:version => 16) do t.column "type", :string t.column "customer_id", :integer t.column "date", :date - t.column "price", :decimal, :precision => 8, :scale => 2, :default => 0.0 + t.column "price", :decimal, :default => 0.0 t.column "rentable_id", :integer - t.column "due_date", :date t.column "merchandise_id", :integer t.column "quantity", :integer end @@ -57,6 +59,9 @@ ActiveRecord::Schema.define(:version => 16) do t.column "platform", :integer end +# Could not dump table "sqlite_sequence" because of following StandardError +# Unknown type '' for column 'name' + create_table "videogenres", :force => true do |t| t.column "name", :string, :null => false end diff --git a/test/fixtures/merchandise_purchases.yml b/test/fixtures/merchandise_purchases.yml new file mode 100644 index 0000000..b49c4eb --- /dev/null +++ b/test/fixtures/merchandise_purchases.yml @@ -0,0 +1,5 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html +one: + id: 1 +two: + id: 2 diff --git a/test/fixtures/rentable_purchases.yml b/test/fixtures/rentable_purchases.yml new file mode 100644 index 0000000..b49c4eb --- /dev/null +++ b/test/fixtures/rentable_purchases.yml @@ -0,0 +1,5 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html +one: + id: 1 +two: + id: 2 diff --git a/test/functional/purchase_controller_test.rb b/test/functional/purchase_controller_test.rb new file mode 100644 index 0000000..bcbcfa7 --- /dev/null +++ b/test/functional/purchase_controller_test.rb @@ -0,0 +1,18 @@ +require File.dirname(__FILE__) + '/../test_helper' +require 'purchase_controller' + +# Re-raise errors caught by the controller. +class PurchaseController; def rescue_action(e) raise e end; end + +class PurchaseControllerTest < Test::Unit::TestCase + def setup + @controller = PurchaseController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + # Replace this with your real tests. + def test_truth + assert true + end +end diff --git a/test/unit/merchandise_purchase_test.rb b/test/unit/merchandise_purchase_test.rb new file mode 100644 index 0000000..85cf484 --- /dev/null +++ b/test/unit/merchandise_purchase_test.rb @@ -0,0 +1,10 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class MerchandisePurchaseTest < Test::Unit::TestCase + fixtures :merchandise_purchases + + # Replace this with your real tests. + def test_truth + assert true + end +end diff --git a/test/unit/rentable_purchase_test.rb b/test/unit/rentable_purchase_test.rb new file mode 100644 index 0000000..327daab --- /dev/null +++ b/test/unit/rentable_purchase_test.rb @@ -0,0 +1,10 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class RentablePurchaseTest < Test::Unit::TestCase + fixtures :rentable_purchases + + # Replace this with your real tests. + def test_truth + assert true + end +end