Lots of stuff, I got too tired to keep perfect revision history
[cs356-p2-videostore.git] / app / controllers / purchase_controller.rb
1 class PurchaseController < ApplicationController
2   layout "admin"
3
4   # Make sure that a user logs in before doing any action here
5   before_filter :authorize, :except => [:filter, :filterbycust, :filterbydate, :filterbytype, :list, :index, :income]
6   before_filter :manager, :only => [:filter, :filterbycust, :filterbydate, :filterbytype, :list, :index, :income]
7
8   def index
9     render :action => 'index'
10   end
11
12   def list
13     @purchase_pages, @purchases = paginate :purchases, :per_page => 100
14   end
15
16   def filter
17     if request.post?
18       type = params[:type]
19       id = params[:id]
20
21       case type
22         when :customer, "customer"
23           redirect_to :action => 'filterbycust', :id => id
24         when :date, "date"
25           date = Date.new id['(1i)'].to_i, id['(2i)'].to_i, id['(3i)'].to_i
26           redirect_to :action => 'filterbydate', :id => date.to_s
27       end
28     else
29       @type = params[:type]
30       if @type.nil?
31         @type = "all"
32       end
33       render :action => 'filter'
34     end
35   end
36
37   def filterbycust
38     @purchase_pages, @purchases = paginate :purchases, :per_page => 100, :conditions => ["customer_id = ?", params[:id]]
39     render :action => 'list'
40   end
41
42   def filterbydate
43     @purchase_pages, @purchases = paginate :purchases, :per_page => 100, :conditions => ["date = ?", params[:id]]
44     render :action => 'list'
45   end
46
47   def filterbytype
48     @purchase_pages, @purchases = paginate :purchases, :per_page => 100, :conditions => ["type = ?", params[:id]]
49     render :action => 'list'
50   end
51
52   def income
53     if request.post?
54       # Find all purchases between :begin_date, and :end_date and sum up the total income
55       # from RentablePurchases, MerchandisePurchases. Print both sums, and the total sum.
56       @begin_date = Date.new params[:begin_date]['(1i)'].to_i, params[:begin_date]['(2i)'].to_i, params[:begin_date]['(3i)'].to_i
57       @end_date = Date.new params[:end_date]['(1i)'].to_i, params[:end_date]['(2i)'].to_i, params[:end_date]['(3i)'].to_i
58       merchandises = MerchandisePurchase.find(:all, :conditions => ['date >= ? AND date <= ?', @begin_date, @end_date])
59       rentables = RentablePurchase.find(:all, :conditions => ['date >= ? AND date <= ?', @begin_date, @end_date])
60       late_fees = LateFeePurchase.find(:all, :conditions => ['date >= ? AND date <= ?', @begin_date, @end_date])
61
62       @merch_count = merchandises.length
63       @rent_count = rentables.length
64       @late_count = late_fees.length
65       @merch_sum = merchandises.sum(&:price)
66       @rent_sum = rentables.sum(&:price)
67       @late_sum = late_fees.sum(&:price)
68       @total = @merch_sum + @rent_sum + @late_sum
69       render :action => 'income_results'
70     else
71       render :action => 'income'
72     end
73   end
74
75   def begin
76     # enter a customer id here
77     render :action => 'begin'
78     session[:total] = 0.00
79     session[:items] = []
80     session[:bonus] = nil
81   end
82
83   def receipt
84     # Save important data, since we're gonna wipe it out now
85     @customer = Customer.find_by_id(session[:customer_id])
86     @debt = @customer.debt
87     @total = session[:total] + @debt
88     @items = session[:items]
89     @bonus = session[:bonus]
90     @time = Time.now
91
92     # Record a Late Fee Payment if we need to
93     if not @debt.zero?
94       purchase = LateFeePurchase.new
95       purchase.customer = @customer
96       purchase.date = Time.now.to_date
97       purchase.price = @debt
98       purchase.save
99     end
100
101     # Set the customer's debt to $0.00, she paid us
102     @customer = Customer.find_by_id(session[:customer_id])
103     @customer.debt = 0.00
104     @customer.save
105
106     # Wipe session data
107     session[:customer_id] = nil
108     session[:total] = nil
109     session[:items] = nil
110     session[:bonus] = nil
111
112     # Show the receipt
113     render :action => 'receipt'
114   end
115
116   def customer_ok
117     if Customer.find_by_id(params[:customer_id])
118       session[:customer_id] = params[:customer_id]
119       redirect_to :action => :menu
120     else
121       flash[:notice] = "Customer ID is invalid"
122       redirect_to :action => :begin
123     end
124   end
125
126   def menu
127     @customer = Customer.find_by_id(session[:customer_id])
128     @total_price = session[:total]
129     @items = session[:items]
130     render :action => 'menu'
131   end
132
133   def rent
134     if request.post?
135       @customer = Customer.find_by_id(session[:customer_id])
136       @rentable = Rentable.find_by_id(params[:rentable_id])
137
138       if @customer.nil?
139         flash[:notice] = "Customer ID is invalid"
140         redirect_to :action => :begin
141         return
142       end
143
144       if @rentable.nil?
145         flash[:notice] = "Rentable ID is invalid"
146         redirect_to :action => :rent
147         return
148       end
149
150       if @rentable.checkedout?
151         flash[:notice] = "This #{@rentable.type} is already checked out!"
152         redirect_to :action => :rent
153         return
154       end
155
156       # Check Rentable Policies
157       @maxvideos = RentablePolicy.find_by_name("MaxVideos")
158       if @rentable.class == Video and @customer.checked_out_videos >= @maxvideos.value
159         flash[:notice] = "#{@maxvideos.description} LIMIT REACHED"
160         redirect_to :action => :rent
161         return
162       end
163
164       @maxgames = RentablePolicy.find_by_name("MaxGames")
165       if @rentable.class == Game and @customer.checked_out_games >= @maxgames.value
166         flash[:notice] = "#{@maxgames.description} LIMIT REACHED"
167         redirect_to :action => :rent
168         return
169       end
170
171       @maxoverduevideos = RentablePolicy.find_by_name("MaxOverdueVideos")
172       if @rentable.class == Video and @customer.overdue_videos >= @maxoverduevideos.value
173         flash[:notice] = "#{@maxoverduevideos.description} LIMIT REACHED"
174         redirect_to :action => :rent
175         return
176       end
177
178       @maxoverduegames = RentablePolicy.find_by_name("MaxOverdueGames")
179       if @rentable.class == Game and @customer.overdue_games >= @maxoverduegames.value
180         flash[:notice] = "#{@maxoverduegames.description} LIMIT REACHED"
181         redirect_to :action => :rent
182         return
183       end
184
185       # Check for a Bonus
186       for bonus in BonusPolicy.find_all_by_bonus_type(@rentable.class.to_s)
187         # Find the earliest the period for this bonus extends
188         since_date = Time.now.advance(:days => (-1 * bonus.days)).to_date
189
190         # Find the date of the latest bonus in this period
191         last_bonus_date = BonusPurchase.last_bonus_date(@customer, @rentable.class, since_date)
192
193         # Find the number of rentals of this type in the period since the last bonus
194         count = 0
195         for rental in RentablePurchase.find_all_by_customer_id(@customer, :conditions => ["date > ?", last_bonus_date])
196           if rental.rentable.class == @rentable.class
197             count += 1
198           end
199         end
200
201         # We are eligible for a bonus!
202         if count >= bonus.number
203
204           # Check out the item
205           checkout = Coitem.new
206           checkout.customer = @customer
207           checkout.rentable = @rentable
208           checkout.out_date = Time.now.to_date
209           checkout.due_date = @rentable.due_date
210           checkout.save!
211
212           # Record the BonusPurchase
213           purchase = BonusPurchase.new
214           purchase.customer = @customer
215           purchase.date = Time.now.to_date
216           purchase.price = @rentable.calculated_price
217           purchase.rentable = @rentable
218           purchase.save!
219
220           # Add to session variables
221           session[:items].push @rentable
222           session[:bonus] = @rentable
223
224           flash[:notice] = "Successfully made bonus purchase"
225           redirect_to :action => :menu
226           return
227         end
228       end
229       
230       # Check out the item
231       checkout = Coitem.new
232       checkout.customer = @customer
233       checkout.rentable = @rentable
234       checkout.out_date = Time.now.to_date
235       checkout.due_date = @rentable.due_date
236       checkout.save!
237
238       # Actually record the purchase
239       purchase = RentablePurchase.new
240       purchase.customer = @customer
241       purchase.date = Time.now.to_date
242       purchase.price = @rentable.calculated_price
243       purchase.rentable = @rentable
244       purchase.save!
245
246       # Add to session variables
247       session[:total] += @rentable.calculated_price
248       session[:items].push @rentable
249
250       flash[:notice] = "Successfully made purchase"
251       redirect_to :action => :menu
252     else
253       render :action => 'rent'
254     end
255   end
256
257   def buy_merch
258     if request.post?
259       @customer = Customer.find_by_id(session[:customer_id])
260       @merchandise = Merchandise.find_by_id(params[:merchandise_id])
261     
262       if @customer.nil?
263         flash[:notice] = "Customer ID is invalid"
264         redirect_to :action => :begin
265         return
266       end
267
268       if @merchandise.nil?
269         flash[:notice] = "Merchandise ID is invalid"
270         redirect_to :action => :buy_merch
271         return
272       end
273
274       if @merchandise.quantity < 1
275         flash[:notice] = "The system thinks we are out of this merchandise item!"
276         redirect_to :action => :buy_merch
277         return
278       end
279
280       # Actually record the purchase
281       purchase = MerchandisePurchase.new
282       purchase.customer = @customer
283       purchase.date = Time.now.to_date
284       purchase.price = @merchandise.price
285       purchase.merchandise = @merchandise
286       purchase.quantity = 1
287       @merchandise.quantity -= 1
288
289       # Add to session variables
290       session[:total] += @merchandise.price
291       session[:items].push @merchandise
292
293       # Save both the merchandise (we changed the quantity) and the purchase to the log
294       @merchandise.save!
295       purchase.save!
296
297       flash[:notice] = "Successfully made purchase"
298       redirect_to :action => :menu
299     else
300       render :action => 'buy_merch'
301     end
302   end
303
304 end