Skip to content
This repository was archived by the owner on Jul 24, 2020. It is now read-only.

Commit bfe944e

Browse files
author
Sydney Young
committed
Add option to disable requests
Resolves #1624 - Adds a Service Object for reservation creation
1 parent 58b7464 commit bfe944e

19 files changed

+361
-278
lines changed

app/controllers/app_configs_controller.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ def app_config_params
7070
:checkout_persons_can_edit, :enable_renewals,
7171
:override_on_create, :override_at_checkout, :require_phone,
7272
:notify_admin_on_create, :disable_user_emails,
73-
:autodeactivate_on_archive, :requests_affect_availability)
73+
:autodeactivate_on_archive, :requests_affect_availability,
74+
:disable_requests)
7475
end
7576
end

app/controllers/reservations_controller.rb

+75-60
Original file line numberDiff line numberDiff line change
@@ -102,80 +102,43 @@ def view_all_dates
102102
def show
103103
end
104104

105-
def new # rubocop:disable MethodLength
105+
def new
106106
if cart.items.empty?
107107
flash[:error] = 'You need to add items to your cart before making a '\
108108
'reservation.'
109109
redirect_loc = (request.env['HTTP_REFERER'].present? ? :back : root_path)
110110
redirect_to redirect_loc
111-
else
112-
# error handling
113-
@errors = cart.validate_all
114-
unless @errors.empty?
115-
if can? :override, :reservation_errors
116-
flash[:error] = 'Are you sure you want to continue? Please review '\
117-
'the errors below.'
118-
else
119-
flash[:error] = 'Please review the errors below. If uncorrected, '\
120-
'any reservations with errors will be filed as a request, and '\
121-
'subject to administrator approval.'
122-
end
123-
end
111+
return
112+
end
124113

114+
# error handling
115+
@errors = cart.validate_all
116+
if @errors.empty?
125117
# this is used to initialize each reservation later
126118
@reservation = Reservation.new(start_date: cart.start_date,
127119
due_date: cart.due_date,
128120
reserver_id: cart.reserver_id)
121+
else
122+
handle_new_reservation_errors
129123
end
130124
end
131125

132-
def create # rubocop:disable all
126+
def create
127+
# store information about the cart because it is purged if reservations
128+
# are successfully created
133129
@errors = cart.validate_all
134-
notes = params[:reservation][:notes]
135-
requested = !@errors.empty? && (cannot? :override, :reservation_errors)
136-
137-
# check for missing notes and validation errors
138-
if !@errors.blank? && notes.blank?
139-
# there were errors but they didn't fill out the notes
140-
flash[:error] = 'Please give a short justification for this '\
141-
"reservation #{requested ? 'request' : 'override'}"
142-
@notes_required = true
143-
if AppConfig.get(:request_text).empty?
144-
@request_text = 'Please give a short justification for this '\
145-
'equipment request.'
146-
else
147-
@request_text = AppConfig.get(:request_text)
148-
end
149-
render(:new) && return
150-
end
151-
152-
Reservation.transaction do
153-
begin
154-
start_date = cart.start_date
155-
reserver = cart.reserver_id
156-
notes = format_errors(@errors) + notes.to_s
157-
if requested
158-
flash[:notice] = cart.request_all(current_user,
159-
params[:reservation][:notes])
160-
else
161-
flash[:notice] = cart.reserve_all(current_user,
162-
params[:reservation][:notes])
163-
end
164-
165-
if (cannot? :manage, Reservation) || (requested == true)
166-
redirect_to(catalog_path) && return
167-
end
168-
if start_date == Time.zone.today
169-
flash[:notice] += ' Are you simultaneously checking out equipment '\
170-
'for someone? Note that only the reservation has been made. '\
171-
'Don\'t forget to continue to checkout.'
172-
end
173-
redirect_to(manage_reservations_for_user_path(reserver)) && return
174-
rescue ActiveRecord::RecordNotSaved, ActiveRecord::RecordInvalid => e
175-
redirect_to catalog_path, flash: { error: 'Oops, something went '\
176-
"wrong with making your reservation.<br/> #{e.message}".html_safe }
177-
raise ActiveRecord::Rollback
178-
end
130+
start_date = cart.start_date
131+
reserver_id = cart.reserver_id
132+
creator =
133+
ReservationCreator.new(cart: cart, current_user: current_user,
134+
override: can?(:override, :reservation_errors),
135+
notes: params[:reservation][:notes])
136+
result = creator.create!
137+
if result[:error]
138+
handle_create_errors(result[:error])
139+
else
140+
handle_create_success(result[:result], start_date, reserver_id,
141+
creator.request?)
179142
end
180143
end
181144

@@ -511,6 +474,58 @@ def archive # rubocop:disable all
511474

512475
private
513476

477+
def handle_new_reservation_errors
478+
if can? :override, :reservation_errors
479+
flash[:error] = 'Are you sure you want to continue? Please review '\
480+
'the errors below.'
481+
render :new
482+
elsif AppConfig.check(:disable_requests)
483+
flash[:error] = 'Please review the errors below.'
484+
render :requests_disabled
485+
else
486+
flash[:error] = 'Please review the errors below. If uncorrected, '\
487+
'any reservations with errors will be filed as a request, and '\
488+
'subject to administrator approval.'
489+
render :new_request
490+
end
491+
end
492+
493+
def handle_create_errors(errors)
494+
case errors
495+
when 'needs notes'
496+
flash[:error] = 'Please give a short justification for this reservation'
497+
@notes_required = true
498+
@request_text = if AppConfig.get(:request_text).empty?
499+
'Please give a short justification for this '\
500+
'equipment request.'
501+
else
502+
AppConfig.get(:request_text)
503+
end
504+
render :new_request
505+
when 'requests disabled'
506+
flash[:error] = 'Unable to create reservation'
507+
render :requests_disabled
508+
else
509+
redirect_to catalog_path,
510+
flash: { error: 'Oops, something went wrong with making '\
511+
"your reservation.<br/> #{errors}".html_safe }
512+
end
513+
end
514+
515+
def handle_create_success(messages, start_date, reserver_id, requested)
516+
flash[:notice] = messages
517+
if can?(:manage, Reservation) && !requested
518+
if start_date == Time.zone.today
519+
flash[:notice] += ' Are you simultaneously checking out equipment '\
520+
'for someone? Note that only the reservation has been made. '\
521+
'Don\'t forget to continue to checkout.'
522+
end
523+
redirect_to(manage_reservations_for_user_path(reserver_id))
524+
else
525+
redirect_to(catalog_path)
526+
end
527+
end
528+
514529
def reservation_params
515530
params.require(:reservation)
516531
.permit(:checkout_handler_id, :checkin_handler_id,

app/views/app_configs/_form.erb

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
<fieldset>
5050
<legend>Reservation Settings</legend><br />
5151
<%= f.input :requests_affect_availability, label: 'Allow requests to affect equipment availability?', hint: 'When enabled, reservation requests will affect equipment item availability before the request is approved.' %>
52+
<%= f.input :disable_requests, label: 'Disable reservation requests?', hint: 'When enabled, users will not be able to create special reservation requests.' %>
5253
<%= f.input :notify_admin_on_create, label: 'Notify admin on creation?',hint: 'When enabled, admins will get an e-mail whenever a reservation is created.' %>
5354
<%= f.input :request_text, label: 'Reservation request text', input_html: {rows: 10},
5455
hint: 'This message will be displayed to users who are about to file a reservation request for invalid reservations. You can use markdown in this field' %>

app/views/cart_js/reservation_form.js.erb

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
resume_cart();
22

33
<% if @errors.empty? or (can? :override, :reservation_errors) %>
4-
$('#confirm-res-form').html('<%= escape_javascript(render :partial => '/reservations/new_reservation') %>');
4+
$('#confirm-res-form').html('<%= escape_javascript(render partial: '/reservations/new_reservation') %>');
55
$('.page-header').html('<h1>Confirm Reservation</h1>');
6+
<% elsif AppConfig.check(:disable_requests) %>
7+
$('#confirm-res-form').html('<%= escape_javascript(render partial: '/reservations/requests_disabled') %>');
8+
$('.page-header').html('<h1>Reservation Denied</h1>');
69
<% else %>
7-
$('#confirm-res-form').html('<%= escape_javascript(render :partial => '/reservations/new_request' ) %>');
10+
$('#confirm-res-form').html('<%= escape_javascript(render partial: '/reservations/new_request' ) %>');
811
$('.page-header').html('<h1>Confirm Reservation Request</h1>');
912
<% end %>
1013

app/views/reservations/_new_request.html.erb

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<div id="content" class="col-md-9">
33
<% unless @errors.empty? %>
44
<p>
5-
<h3><i class="fa fa-exclamation-triangle warning-icon"></i> Would you like to resolve the following error(s)?</h3>
5+
<h3><i class="fa fa-exclamation-triangle warning-icon"></i> Would you like to resolve the following error(s)?</h3>
66
</p>
77
<div class ="form-errors">
88
<% @errors.each do |msg| %>
@@ -13,13 +13,13 @@
1313
</div>
1414
<% end %>
1515
<p>
16-
<h4>Equipment requested for
16+
<h4>Equipment requested for
1717
<%= link_to User.find(cart.reserver_id).name, User.find(cart.reserver_id),
18-
target: '_blank' %>
18+
target: '_blank' %>
1919
from
2020
<%= cart.start_date.to_s(:long) %> to
2121
<%= cart.due_date.to_s(:long) %>:
22-
</h4>
22+
</h4>
2323
</p>
2424
<%= render partial: 'reservations/edit_reservation_form' %>
2525
<div class="well">

app/views/reservations/_new_reservation.html.erb

+7-7
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
<div id="content" class="col-md-9">
44
<% unless @errors.empty? %>
55
<p>
6-
<h3>
7-
<i class="fa fa-exclamation-triangle warning-icon"></i>
8-
Please be aware of the following errors:
9-
</h3>
6+
<h3>
7+
<i class="fa fa-exclamation-triangle warning-icon"></i>
8+
Please be aware of the following errors:
9+
</h3>
1010
</p>
1111
<div class ="form-errors">
1212
<% @errors.each do |msg| %>
@@ -17,13 +17,13 @@
1717
</div>
1818
<% end %>
1919
<p>
20-
<h4>Equipment Reserved for
20+
<h4>Equipment Reserved for
2121
<%= link_to User.find(cart.reserver_id).name, User.find(cart.reserver_id),
22-
target: '_blank' %>
22+
target: '_blank' %>
2323
from
2424
<%= cart.start_date.to_s(:long) %> to
2525
<%= cart.due_date.to_s(:long) %>:
26-
</h4>
26+
</h4>
2727
</p>
2828
<%= render partial: 'reservations/edit_reservation_form' %>
2929
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<% title "Reservation Denied" %>
2+
<div id="content" class="col-md-9">
3+
<% unless @errors.empty? %>
4+
<p>
5+
<h3><i class="fa fa-exclamation-triangle warning-icon"></i> Please resolve the following error(s):</h3>
6+
</p>
7+
<div class ="form-errors">
8+
<% @errors.each do |msg| %>
9+
<ul>
10+
<li><%= msg %></li>
11+
</ul>
12+
<% end %>
13+
</div>
14+
<% end %>
15+
<p>
16+
<h4>Equipment requested for
17+
<%= link_to User.find(cart.reserver_id).name, User.find(cart.reserver_id),
18+
target: '_blank' %>
19+
from
20+
<%= cart.start_date.to_s(:long) %> to
21+
<%= cart.due_date.to_s(:long) %>:
22+
</h4>
23+
</p>
24+
<%= render partial: 'reservations/edit_reservation_form' %>
25+
<%= simple_form_for @reservation do |f| %>
26+
<div class="form-group">
27+
<%= f.button :submit, "Submit", id: 'finalize_reservation_btn' %>
28+
</div>
29+
<% end %>
30+
</div>
31+
<div id="sidebar" class="col-md-3">
32+
<div id="sidebarbottom">
33+
<div id="cart" class="well">
34+
<div id="cartSpinner"></div>
35+
<header class="cart-header">
36+
<% if cannot? :manage, Reservation %>
37+
<h2>My Cart</h2>
38+
<% else %>
39+
<h2>Cart</h2>
40+
<% end %>
41+
</header>
42+
<%= form_tag url_for(action: 'change_reservation_dates', controller: "catalog"), remote: true, class: 'form-vertical', id: 'dates_form', method: :put do %>
43+
<%# allow user to set start/end dates %>
44+
<%= render partial: 'reservations/cart_dates' %>
45+
<% end %>
46+
<br>
47+
</div>
48+
</div>
49+
</div>

app/views/reservations/new.html.erb

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
11
<div id='confirm-res-form'>
2-
<% if @errors.empty? or (can? :override, :reservation_errors) %>
3-
<%= render :partial => "new_reservation" %>
4-
<% else %>
5-
<%= render :partial => "new_request" %>
6-
<% end %>
7-
</div>
2+
<%= render partial: 'new_reservation' %>
3+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div id='confirm-res-form'>
2+
<%= render partial: 'new_request' %>
3+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div id='confirm-res-form'>
2+
<%= render partial: 'requests_disabled' %>
3+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AddDisableRequestsToAppConfigs < ActiveRecord::Migration
2+
def change
3+
add_column :app_configs, :disable_requests, :boolean, default: false
4+
end
5+
end

db/schema.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#
1212
# It's strongly recommended that you check this file into your version control system.
1313

14-
ActiveRecord::Schema.define(version: 20160610135455) do
14+
ActiveRecord::Schema.define(version: 20160809194337) do
1515

1616
create_table "announcements", force: :cascade do |t|
1717
t.text "message", limit: 65535
@@ -58,6 +58,7 @@
5858
t.boolean "disable_user_emails", default: false
5959
t.boolean "autodeactivate_on_archive", default: false
6060
t.boolean "requests_affect_availability", default: false
61+
t.boolean "disable_requests", default: false
6162
end
6263

6364
create_table "blackouts", force: :cascade do |t|

lib/reservation_creator.rb

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# frozen_string_literal: true
2+
class ReservationCreator
3+
# Service Object to create reservations in the reservations controller
4+
def initialize(cart:, current_user:, override: false, notes: '')
5+
@current_user = current_user
6+
@cart = cart
7+
@cart_errors = cart.validate_all
8+
@override = override
9+
@notes = notes
10+
end
11+
12+
def create!
13+
return { result: nil, error: error } if error
14+
reservation_transaction
15+
end
16+
17+
def request?
18+
!override && !cart_errors.blank?
19+
end
20+
21+
private
22+
23+
attr_reader :cart, :current_user, :override, :notes, :cart_errors
24+
25+
def error
26+
return 'requests disabled' if request? && AppConfig.check(:disable_requests)
27+
return 'needs notes' if needs_notes?
28+
end
29+
30+
def needs_notes?
31+
(request? || override?) && notes.blank?
32+
end
33+
34+
def override?
35+
override && !cart_errors.blank?
36+
end
37+
38+
def reservation_transaction
39+
result = {}
40+
Reservation.transaction do
41+
begin
42+
create_method = request? ? :request_all : :reserve_all
43+
cart_result = cart.send(create_method, current_user, notes)
44+
result = { result: cart_result, error: nil }
45+
rescue ActiveRecord::RecordNotSaved, ActiveRecord::RecordInvalid => e
46+
result = { result: nil, error: e.message }
47+
raise ActiveRecord::Rollback
48+
end
49+
end
50+
result
51+
end
52+
end

0 commit comments

Comments
 (0)