From 681579efc209ea5e392efa7c4838da690ee1a695 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Tue, 5 Sep 2017 14:24:07 -0700 Subject: [PATCH 01/27] Setup of project structure for Hotel project --- Rakefile | 9 +++++++++ lib/Booking.rb | 15 +++++++++++++++ lib/Guest.rb | 7 +++++++ lib/Reservation.rb | 8 ++++++++ lib/Room.rb | 8 ++++++++ specs/Booking_spec.rb | 1 + specs/Guest_spec.rb | 3 +++ specs/Reservation_spec.rb | 1 + specs/Room_spec.rb | 1 + specs/spec_helper.rb | 11 +++++++++++ 10 files changed, 64 insertions(+) create mode 100644 Rakefile create mode 100644 lib/Booking.rb create mode 100644 lib/Guest.rb create mode 100644 lib/Reservation.rb create mode 100644 lib/Room.rb create mode 100644 specs/Booking_spec.rb create mode 100644 specs/Guest_spec.rb create mode 100644 specs/Reservation_spec.rb create mode 100644 specs/Room_spec.rb create mode 100644 specs/spec_helper.rb diff --git a/Rakefile b/Rakefile new file mode 100644 index 000000000..f4f704fca --- /dev/null +++ b/Rakefile @@ -0,0 +1,9 @@ +require 'rake/testtask' + +Rake::TestTask.new do |t| + t.libs = ["lib"] + t.warning = false + t.test_files = FileList['specs/*_spec.rb'] +end + +task default: :test diff --git a/lib/Booking.rb b/lib/Booking.rb new file mode 100644 index 000000000..9fcc9043a --- /dev/null +++ b/lib/Booking.rb @@ -0,0 +1,15 @@ +### Booking Program class that holds all of the business logic for the hotel and the reservation system + +module Hotel + # NUMBER_OF_ROOMS = 20 ### might not want to use constant, especially if we have subclasses of rooms (by type), and each room subclass might have a different number. may best be a constant defined by class/subclass + + class BookingProgram + #rooms = Hotel::Room.all # returns an array or hash of Room objects + + #reservations = Hotel::Reservation.all #returns an array or hash of Reservation Objects + + # puts " rooms: #{rooms} \n reservations: #{reservations}" + + + end +end diff --git a/lib/Guest.rb b/lib/Guest.rb new file mode 100644 index 000000000..713db0698 --- /dev/null +++ b/lib/Guest.rb @@ -0,0 +1,7 @@ +### OPTIONAL CLASS + +module Hotel + class Guest + + end +end diff --git a/lib/Reservation.rb b/lib/Reservation.rb new file mode 100644 index 000000000..93269c245 --- /dev/null +++ b/lib/Reservation.rb @@ -0,0 +1,8 @@ + +module Hotel + + class Reservation + + end + +end diff --git a/lib/Room.rb b/lib/Room.rb new file mode 100644 index 000000000..752a807fa --- /dev/null +++ b/lib/Room.rb @@ -0,0 +1,8 @@ + +module Hotel + + class Room + + end + +end diff --git a/specs/Booking_spec.rb b/specs/Booking_spec.rb new file mode 100644 index 000000000..ae9c220ea --- /dev/null +++ b/specs/Booking_spec.rb @@ -0,0 +1 @@ +require_relative 'spec_helper' diff --git a/specs/Guest_spec.rb b/specs/Guest_spec.rb new file mode 100644 index 000000000..234bbeaa5 --- /dev/null +++ b/specs/Guest_spec.rb @@ -0,0 +1,3 @@ +### OPTIONAL CLASS + +require_relative 'spec_helper' diff --git a/specs/Reservation_spec.rb b/specs/Reservation_spec.rb new file mode 100644 index 000000000..ae9c220ea --- /dev/null +++ b/specs/Reservation_spec.rb @@ -0,0 +1 @@ +require_relative 'spec_helper' diff --git a/specs/Room_spec.rb b/specs/Room_spec.rb new file mode 100644 index 000000000..ae9c220ea --- /dev/null +++ b/specs/Room_spec.rb @@ -0,0 +1 @@ +require_relative 'spec_helper' diff --git a/specs/spec_helper.rb b/specs/spec_helper.rb new file mode 100644 index 000000000..6f9528f7c --- /dev/null +++ b/specs/spec_helper.rb @@ -0,0 +1,11 @@ +require 'simplecov' +SimpleCov.start +require 'minitest/autorun' +require 'minitest/reporters' +require 'minitest/skip_dsl' +require_relative '../lib/Booking' +require_relative '../lib/Reservation' +require_relative '../lib/Room' +require_relative '../lib/Guest' + +Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new From 86e2d67efbc59d50757d6842fef1d294453c73c5 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Tue, 5 Sep 2017 14:44:30 -0700 Subject: [PATCH 02/27] Created and tested initialize methods for Hotel::Room class --- lib/Room.rb | 10 ++++++++++ specs/Room_spec.rb | 29 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/lib/Room.rb b/lib/Room.rb index 752a807fa..e5396eadd 100644 --- a/lib/Room.rb +++ b/lib/Room.rb @@ -1,8 +1,18 @@ +require 'pry' module Hotel class Room + attr_reader :id, :status, :nightly_rate + + def initialize(id_number, nightly_rate = 200) + @id = id_number + @status = :available + @nightly_rate = nightly_rate + end end end + +# binding.pry diff --git a/specs/Room_spec.rb b/specs/Room_spec.rb index ae9c220ea..220108f9e 100644 --- a/specs/Room_spec.rb +++ b/specs/Room_spec.rb @@ -1 +1,30 @@ require_relative 'spec_helper' + +describe "Hotel::Room class" do + describe "initialize" do + it "requires one argument, number" do + proc {Hotel::Room.new}.must_raise ArgumentError + + new_room = Hotel::Room.new(1) + new_room.must_be_instance_of Hotel::Room + end + + it "creates a new Room object with the correct id, and initialized with the correct default values for status and nightly_rate" do + new_room = Hotel::Room.new(1) + + new_room.id.must_equal 1 + new_room.status.must_equal :available + new_room.nightly_rate.must_equal 200 + end + + it "can take an optional argument nightly_rate if we want to give it a different nightly_rate" do + vip_room = Hotel::Room.new(100, 350) + + vip_room.id.must_equal 100 + vip_room.nightly_rate.must_equal 350 + end + + end #end initialize + + +end #end Hotel::Room class tests From 09030e3c19f13e7da52ff4e52a7b2d4428b03b49 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Wed, 6 Sep 2017 12:45:16 -0700 Subject: [PATCH 03/27] First draft of reserve room method and tests written, passing; placeholder for potential future Reservation class methods inserted --- lib/Reservation.rb | 25 +++++++++++++++ lib/Room.rb | 77 +++++++++++++++++++++++++++++++++++++++++++++- specs/Room_spec.rb | 42 +++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 1 deletion(-) diff --git a/lib/Reservation.rb b/lib/Reservation.rb index 93269c245..008aa8d45 100644 --- a/lib/Reservation.rb +++ b/lib/Reservation.rb @@ -1,7 +1,32 @@ +require 'pry' module Hotel class Reservation + attr_reader :id, :guest, :check_in, :check_out, :room + + def initialize(id, guest, check_in,check_out,room_id) + @id = id + @guest = guest #Optional- create guest object + @check_in = check_in #ruby Date object + @check_out = check_out #ruby Date object + @room= room_id # later, this will be a room object assigned via namespacing method Hotel::Room.find_by(room_id) + end #end initialize + + # def self.all + # end + + # def self.find_by_guest(guest_id) + # end + # + # def self.find_by_date(check_in, check_out) + # end + # + # def self.find_by_room(room_id) + # end + + #def self.find_by_id(reservation_id) + #end end diff --git a/lib/Room.rb b/lib/Room.rb index e5396eadd..43949cceb 100644 --- a/lib/Room.rb +++ b/lib/Room.rb @@ -1,14 +1,60 @@ require 'pry' +require 'date' +require_relative 'Reservation' module Hotel class Room - attr_reader :id, :status, :nightly_rate + attr_reader :id, :status, :nightly_rate, :type, :reserved_dates + + @@total_num_rooms = 20 def initialize(id_number, nightly_rate = 200) @id = id_number @status = :available @nightly_rate = nightly_rate + @type = :standard + @reserved_dates = {} + # holds all reservations, a hash with reservation ids as keys and values as the date range of the reservation ### check-out date should not be included + + end + + def reserve_room(check_in_str,check_out_str,reservation_id, guest_id) + check_in = Date.parse(check_in_str) + check_out = Date.parse(check_out_str) + + all_dates = @reserved_dates.values.flatten + + (check_in...check_out).each do |date| + return false if all_dates.include?(date) + end + + @reserved_dates[reservation_id] = [] + + (check_in...check_out).each do |date| + @reserved_dates[reservation_id] << date + end + + end + + def self.all + i = 1 + all_rooms = [] + + until all_rooms.count == @@total_num_rooms + room = Hotel::Room.new(i) + all_rooms << room + i += 1 + end + + return all_rooms + end + + + def self.find_by_id(room_id) + self.all.each {|room| return room if room.id == room_id} + + raise ArgumentError.new "Sorry, we don't have a room matching that ID number." end end @@ -16,3 +62,32 @@ def initialize(id_number, nightly_rate = 200) end # binding.pry + + +##########Wave 2 + +# def available?(date_str) +# #date format is year, month, day +# date = Date.parse(date_str) +# return false if @reserved_dates.values.include?(date) +# return true +# end +# +# def available_all_days?(check_in_str, check_out_str) +# check_in = Date.parse(check_in_str) +# check_out = Date.parse(check_out_str) +# +# (check_in...check_out).each do |date| +# return false if available?(date) == false +# end +# +# return true +# end + +# def reserve_room(check_in,check_out,res_id, guest_id,room_id) +# if available_all_days?(check_in,check_out) +# reserved_dates[res_id] = (check_in...check_out) #range of dates, maybe stored as array? +# +# end +# +# end diff --git a/specs/Room_spec.rb b/specs/Room_spec.rb index 220108f9e..61b6d2383 100644 --- a/specs/Room_spec.rb +++ b/specs/Room_spec.rb @@ -1,5 +1,8 @@ +require 'date' +require 'pry' require_relative 'spec_helper' + describe "Hotel::Room class" do describe "initialize" do it "requires one argument, number" do @@ -26,5 +29,44 @@ end #end initialize + describe "reserve_room" do + it "can reserve a room if given the check-in/out date, reservation id, and guest id" do + room = Hotel::Room.new(666) + check_in_str = "2017-08-09" + check_out_str = "2017-08-12" + + room.reserve_room(check_in_str, check_out_str, 1, 13) + + binding.pry + + all_dates = room.reserved_dates.values.flatten + + (Date.parse(check_in_str)...Date.parse(check_out_str)).each do |date| + all_dates.must_include date + end + + room.reserve_room("2017-08-10", "2017-08-11", 42, 16).must_equal false + end + + end #end reserve_room + + describe "self.all" do + it "returns an array of all room objects, with the accurate number of rooms" do + test_all_rooms = Hotel::Room.all + + test_all_rooms.must_be_instance_of Array + + test_all_rooms.each do |room| + room.must_be_instance_of Hotel::Room + end + + test_all_rooms.count.must_equal 20 + + end + + + + end #end self.all + end #end Hotel::Room class tests From 75897f5b09f7a52ef532dd336ecc849e8730a741 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Wed, 6 Sep 2017 13:31:53 -0700 Subject: [PATCH 04/27] added Room.find_by_id method to find a room by it's room number --- lib/Room.rb | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/lib/Room.rb b/lib/Room.rb index 43949cceb..470c96226 100644 --- a/lib/Room.rb +++ b/lib/Room.rb @@ -5,17 +5,20 @@ module Hotel class Room - attr_reader :id, :status, :nightly_rate, :type, :reserved_dates + attr_reader :id, :nightly_rate, :type, :reserv_id_and_dates, :all_dates + # :status @@total_num_rooms = 20 def initialize(id_number, nightly_rate = 200) @id = id_number - @status = :available @nightly_rate = nightly_rate @type = :standard - @reserved_dates = {} + @reserv_id_and_dates = {} # holds all reservations, a hash with reservation ids as keys and values as the date range of the reservation ### check-out date should not be included + @all_dates = [] + + # @status = :available #not sure if status is needed anymore.maybe a method, available? end @@ -23,18 +26,19 @@ def reserve_room(check_in_str,check_out_str,reservation_id, guest_id) check_in = Date.parse(check_in_str) check_out = Date.parse(check_out_str) - all_dates = @reserved_dates.values.flatten - (check_in...check_out).each do |date| - return false if all_dates.include?(date) + return false if @all_dates.include?(date) end - @reserved_dates[reservation_id] = [] + @reserv_id_and_dates[reservation_id] = [] (check_in...check_out).each do |date| - @reserved_dates[reservation_id] << date + @reserv_id_and_dates[reservation_id] << date end + @all_dates = @reserv_id_and_dates.values.flatten + ### future note- would it be helpful to sort, and do binary search instead of include? look into it + end def self.all @@ -69,7 +73,7 @@ def self.find_by_id(room_id) # def available?(date_str) # #date format is year, month, day # date = Date.parse(date_str) -# return false if @reserved_dates.values.include?(date) +# return false if @reserv_id_and_dates.values.include?(date) # return true # end # @@ -84,6 +88,17 @@ def self.find_by_id(room_id) # return true # end +# def available_all_days?(check_in_str, check_out_str) +# check_in = Date.parse(check_in_str) +# check_out = Date.parse(check_out_str) +# +# (check_in...check_out).each do |date| +# return false if @all_dates.include?(date) +# end +# +# return true +# end + # def reserve_room(check_in,check_out,res_id, guest_id,room_id) # if available_all_days?(check_in,check_out) # reserved_dates[res_id] = (check_in...check_out) #range of dates, maybe stored as array? From b2cd5f1abc6a5ad0b58fc57e17700904ea73f8b5 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Wed, 6 Sep 2017 13:33:34 -0700 Subject: [PATCH 05/27] tested that I could have multiple reservations on the same room --- specs/Room_spec.rb | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/specs/Room_spec.rb b/specs/Room_spec.rb index 61b6d2383..0bc7a5c19 100644 --- a/specs/Room_spec.rb +++ b/specs/Room_spec.rb @@ -16,7 +16,6 @@ new_room = Hotel::Room.new(1) new_room.id.must_equal 1 - new_room.status.must_equal :available new_room.nightly_rate.must_equal 200 end @@ -37,15 +36,24 @@ room.reserve_room(check_in_str, check_out_str, 1, 13) - binding.pry - - all_dates = room.reserved_dates.values.flatten - (Date.parse(check_in_str)...Date.parse(check_out_str)).each do |date| - all_dates.must_include date + room.all_dates.must_include date end room.reserve_room("2017-08-10", "2017-08-11", 42, 16).must_equal false + + check_in_str2 = "2017-09-28" + check_out_str2 = "2017-10-1" + + room.reserve_room(check_in_str2, check_out_str2, 8, 23) + (Date.parse(check_in_str2)...Date.parse(check_out_str2)).each do |date| + room.all_dates.must_include date + end + + end + + it "doesn't accept dates that are earlier than today's date" do + end end #end reserve_room From 9b1783ae0221ea482c1c4c7a35c75cb7ac6cde21 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Wed, 6 Sep 2017 15:44:29 -0700 Subject: [PATCH 06/27] get a list of all reservations on a certain date; wrote basic functionality and basic tests; passing --- lib/Booking.rb | 52 ++++++++++++++++++++++++++++++++++++++++--- specs/Booking_spec.rb | 40 +++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/lib/Booking.rb b/lib/Booking.rb index 9fcc9043a..7ea21c2c6 100644 --- a/lib/Booking.rb +++ b/lib/Booking.rb @@ -1,15 +1,61 @@ ### Booking Program class that holds all of the business logic for the hotel and the reservation system +require 'date' +require 'pry' +require_relative 'Reservation' +require_relative 'Room' module Hotel # NUMBER_OF_ROOMS = 20 ### might not want to use constant, especially if we have subclasses of rooms (by type), and each room subclass might have a different number. may best be a constant defined by class/subclass class BookingProgram - #rooms = Hotel::Room.all # returns an array or hash of Room objects + attr_reader :all_rooms, :all_reservations - #reservations = Hotel::Reservation.all #returns an array or hash of Reservation Objects + def initialize # do we want to initialize with hotel name? + @all_rooms = Hotel::Room.all # returns an array or hash of Room objects + @all_reservations = [] - # puts " rooms: #{rooms} \n reservations: #{reservations}" + end + def make_reservation(guest_id, check_in,check_out,room_id) + + reservation = Hotel::Reservation.new(guest_id, check_in,check_out,room_id) + reservation.id += 1 #something + + reservation.room.reserve_room(check_in,check_out,reservation.id, guest_id) + + @all_reservations << reservation + + end + + def find_res_by_date(date_str) + date_object= Date.parse(date_str) + reserved_on_date = [] + @all_reservations.each {|reservation| reserved_on_date << reservation if reservation.room.all_dates.include?(date_object)} + + return reserved_on_date + + #self.all.select {|reservation| reservation.room.all_dates.include?(date_object)} + end end + end + + +# binding.pry + +#########WAVE 2 ##### + +# def available_rooms(check_in,check_out) +# # confirm check_out date availability logic +# available_rooms = [] +# +# candidates = @all_rooms.select {|room| room.available?(check_in) && room.available?(check_out)} +# +# candidates.each do |room| +# available_rooms << room if room.available_all_days?(check_in, check_out) +# end +# +# return available_rooms if available_rooms.count > 0 +# return false +# end diff --git a/specs/Booking_spec.rb b/specs/Booking_spec.rb index ae9c220ea..e75b61780 100644 --- a/specs/Booking_spec.rb +++ b/specs/Booking_spec.rb @@ -1 +1,41 @@ require_relative 'spec_helper' + +describe "BookingProgram" do + describe "Initialize" do + it "initializes with 20 rooms, numbered 1 through 20 and I can can access the list of all rooms " do + new_hotel = Hotel::BookingProgram.new + + new_hotel.all_rooms.must_be_instance_of Array + new_hotel.all_rooms.each do |room| + room.must_be_instance_of Hotel::Room + end + + + end + + end + + describe "find_res_by_date" do + it "Returns an array of Reservation objects" do + new_hotel = Hotel::BookingProgram.new + + new_hotel.make_reservation(1, "2017-03-14", "2017-04-16", 3) + + new_hotel.make_reservation(2, "2017-03-14", "2017-04-16", 5) + + new_hotel.make_reservation(3, "2017-02-02", "2017-02-08", 18) + + new_hotel.make_reservation(5, "2017-12-08", "2017-12-10", 7) + + new_hotel.make_reservation(4, "2017-03-21", "2017-03-22", 15) + + + new_hotel.find_res_by_date("2017-03-21").must_be_instance_of Array + + new_hotel.find_res_by_date("2017-03-21").count.must_equal 3 + + p new_hotel.find_res_by_date("2017-03-21") + + end + end +end From 531f35e457225b2a6dabc5d9f54d7fbcc5ed8232 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Wed, 6 Sep 2017 15:45:28 -0700 Subject: [PATCH 07/27] Added test for checking that each room has a nightly rate of 00 --- specs/Room_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/Room_spec.rb b/specs/Room_spec.rb index 0bc7a5c19..b781c438a 100644 --- a/specs/Room_spec.rb +++ b/specs/Room_spec.rb @@ -66,6 +66,7 @@ test_all_rooms.each do |room| room.must_be_instance_of Hotel::Room + room.nightly_rate.must_equal 200 end test_all_rooms.count.must_equal 20 From 3638f068ed3ccd7b2d94e2151a83ce6b87085cb7 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Wed, 6 Sep 2017 16:15:06 -0700 Subject: [PATCH 08/27] Wrote cost method that returns the total cost of a reservation, basic tests passing --- lib/Reservation.rb | 35 +++++++++++++++++-------- specs/Reservation_spec.rb | 54 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 11 deletions(-) diff --git a/lib/Reservation.rb b/lib/Reservation.rb index 008aa8d45..2406bff7e 100644 --- a/lib/Reservation.rb +++ b/lib/Reservation.rb @@ -1,26 +1,39 @@ require 'pry' - +require 'date' module Hotel class Reservation - attr_reader :id, :guest, :check_in, :check_out, :room + attr_reader :guest, :check_in, :check_out, :room + attr_accessor :all_reservations, :id + + @@all_reservations = [] - def initialize(id, guest, check_in,check_out,room_id) - @id = id + def initialize(guest, check_in,check_out,room_id) + @id = 1 @guest = guest #Optional- create guest object - @check_in = check_in #ruby Date object - @check_out = check_out #ruby Date object - @room= room_id # later, this will be a room object assigned via namespacing method Hotel::Room.find_by(room_id) + @check_in = Date.parse(check_in) #ruby Date object + @check_out = Date.parse(check_out) #ruby Date object + @room= Hotel::Room.find_by_id(room_id) # later, this will be a room object assigned via namespacing method Hotel::Room.find_by(room_id) + @totalcost = 200 end #end initialize - # def self.all - # end + + def self.all #returns array + all_reservations = [] + + return all_reservations + + end + + def cost + @totalcost = (check_out.mjd - check_in.mjd)* @room.nightly_rate + return @totalcost + end # def self.find_by_guest(guest_id) # end # - # def self.find_by_date(check_in, check_out) - # end + # # def self.find_by_room(room_id) # end diff --git a/specs/Reservation_spec.rb b/specs/Reservation_spec.rb index ae9c220ea..0bcf48d4b 100644 --- a/specs/Reservation_spec.rb +++ b/specs/Reservation_spec.rb @@ -1 +1,55 @@ require_relative 'spec_helper' + +describe "Hotel::Reservation class" do + describe "initialize" do + it "requires five arguments, an id, a guest, a check-in date, a check-out date, and a room" do + proc {Hotel::Reservation.new}.must_raise ArgumentError + proc {Hotel::Reservation.new("Jim Bob", "2017-07-01",5)}.must_raise ArgumentError + + new_res = Hotel::Reservation.new("Jim Bob", "July 1", "2017-07-03", 5) + + new_res.must_be_instance_of Hotel::Reservation + end + + it "creates a Reservation instance that allows us to read the id, guest, check-in date, check-out date, and room " do + read_res = Hotel::Reservation.new("Dale Cooper", "2017-07-01", "2017-07-03", 5) + + read_res.must_be_instance_of Hotel::Reservation + [read_res.check_in, read_res.check_out].each do |date| + date.month.must_equal 7 + end + + read_res.check_in.day.must_equal 1 + read_res.check_out.day.must_equal 3 + + read_res.room.id.must_equal 5 + read_res.guest.must_equal "Dale Cooper" + end + + end #end initialize tests + + describe "self.all" do + it "initializes with zero reservations" do + new_hotel_reservations = Hotel::Reservation.all + + new_hotel_reservations.must_be_instance_of Array + new_hotel_reservations.count.must_equal 0 + end + + + end #end self.all + + + describe "Cost" do + it "Returns an integer value that is the total cost of the reservation" do + reservation = Hotel::Reservation.new(1,"2017-02-14", "2017-02-16",5) + + reservation.cost.must_equal 400 + + res2 = Hotel::Reservation.new(3, "2017-12-01", "2017-12-02", 17) + + res2.cost.must_equal 200 + end + + end +end From 100fffe12869553d643a63372a8d63ff11872010 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Wed, 6 Sep 2017 16:33:32 -0700 Subject: [PATCH 09/27] BENCHMARK: Wave 1 test requirements with basic test passing. More thorough testing required, error handling, and edge case testing required --- lib/Room.rb | 30 +++++++++++++++++++++++++++++- specs/Booking_spec.rb | 16 ++++++++-------- specs/Reservation_spec.rb | 10 +++++----- specs/Room_spec.rb | 24 ++++++++++++++++++------ 4 files changed, 60 insertions(+), 20 deletions(-) diff --git a/lib/Room.rb b/lib/Room.rb index 470c96226..92a646317 100644 --- a/lib/Room.rb +++ b/lib/Room.rb @@ -26,6 +26,15 @@ def reserve_room(check_in_str,check_out_str,reservation_id, guest_id) check_in = Date.parse(check_in_str) check_out = Date.parse(check_out_str) + + if check_in < Date.today || check_out < Date.today + raise ArgumentError.new("Can't make reservations for days earlier than today") + end + + if check_in.class != Date ||check_out.class != Date + raise ArgumentError.new("Please provide a valid date") + end + (check_in...check_out).each do |date| return false if @all_dates.include?(date) end @@ -37,7 +46,8 @@ def reserve_room(check_in_str,check_out_str,reservation_id, guest_id) end @all_dates = @reserv_id_and_dates.values.flatten - ### future note- would it be helpful to sort, and do binary search instead of include? look into it + ### future note- would it be helpful to sort, and do binary search instead of include? look into it + end @@ -106,3 +116,21 @@ def self.find_by_id(room_id) # end # # end + + + + +#BEGIN RESCUE CLAUSE + +# begin +# if check_in < Date.today || check_out < Date.today +# raise ArgumentError.new("Can't make reservations for days earlier than today") +# end +# +# if check_in.class != Date ||check_out.class != Date +# raise ArgumentError.new("Please provide the date in the following format: \n YYYY-MM-DD") +# end + +# rescue ArgumentError => exception +# puts "Encountered an error: #{exception}" +# end diff --git a/specs/Booking_spec.rb b/specs/Booking_spec.rb index e75b61780..ae20f2914 100644 --- a/specs/Booking_spec.rb +++ b/specs/Booking_spec.rb @@ -19,22 +19,22 @@ it "Returns an array of Reservation objects" do new_hotel = Hotel::BookingProgram.new - new_hotel.make_reservation(1, "2017-03-14", "2017-04-16", 3) + new_hotel.make_reservation(1, "2018-03-14", "2018-04-16", 3) - new_hotel.make_reservation(2, "2017-03-14", "2017-04-16", 5) + new_hotel.make_reservation(2, "2018-03-14", "2018-04-16", 5) - new_hotel.make_reservation(3, "2017-02-02", "2017-02-08", 18) + new_hotel.make_reservation(3, "2018-02-02", "2018-02-08", 18) - new_hotel.make_reservation(5, "2017-12-08", "2017-12-10", 7) + new_hotel.make_reservation(5, "2018-12-08", "2018-12-10", 7) - new_hotel.make_reservation(4, "2017-03-21", "2017-03-22", 15) + new_hotel.make_reservation(4, "2018-03-21", "2018-03-22", 15) - new_hotel.find_res_by_date("2017-03-21").must_be_instance_of Array + new_hotel.find_res_by_date("2018-03-21").must_be_instance_of Array - new_hotel.find_res_by_date("2017-03-21").count.must_equal 3 + new_hotel.find_res_by_date("2018-03-21").count.must_equal 3 - p new_hotel.find_res_by_date("2017-03-21") + p new_hotel.find_res_by_date("2018-03-21") end end diff --git a/specs/Reservation_spec.rb b/specs/Reservation_spec.rb index 0bcf48d4b..67cb5b599 100644 --- a/specs/Reservation_spec.rb +++ b/specs/Reservation_spec.rb @@ -4,15 +4,15 @@ describe "initialize" do it "requires five arguments, an id, a guest, a check-in date, a check-out date, and a room" do proc {Hotel::Reservation.new}.must_raise ArgumentError - proc {Hotel::Reservation.new("Jim Bob", "2017-07-01",5)}.must_raise ArgumentError + proc {Hotel::Reservation.new("Jim Bob", "2018-07-01",5)}.must_raise ArgumentError - new_res = Hotel::Reservation.new("Jim Bob", "July 1", "2017-07-03", 5) + new_res = Hotel::Reservation.new("Jim Bob", "July 1", "2018-07-03", 5) new_res.must_be_instance_of Hotel::Reservation end it "creates a Reservation instance that allows us to read the id, guest, check-in date, check-out date, and room " do - read_res = Hotel::Reservation.new("Dale Cooper", "2017-07-01", "2017-07-03", 5) + read_res = Hotel::Reservation.new("Dale Cooper", "2018-07-01", "2018-07-03", 5) read_res.must_be_instance_of Hotel::Reservation [read_res.check_in, read_res.check_out].each do |date| @@ -42,11 +42,11 @@ describe "Cost" do it "Returns an integer value that is the total cost of the reservation" do - reservation = Hotel::Reservation.new(1,"2017-02-14", "2017-02-16",5) + reservation = Hotel::Reservation.new(1,"2018-02-14", "2018-02-16",5) reservation.cost.must_equal 400 - res2 = Hotel::Reservation.new(3, "2017-12-01", "2017-12-02", 17) + res2 = Hotel::Reservation.new(3, "2018-12-01", "2018-12-02", 17) res2.cost.must_equal 200 end diff --git a/specs/Room_spec.rb b/specs/Room_spec.rb index b781c438a..b450500f4 100644 --- a/specs/Room_spec.rb +++ b/specs/Room_spec.rb @@ -31,8 +31,8 @@ describe "reserve_room" do it "can reserve a room if given the check-in/out date, reservation id, and guest id" do room = Hotel::Room.new(666) - check_in_str = "2017-08-09" - check_out_str = "2017-08-12" + check_in_str = "2018-08-09" + check_out_str = "2018-08-12" room.reserve_room(check_in_str, check_out_str, 1, 13) @@ -40,19 +40,31 @@ room.all_dates.must_include date end - room.reserve_room("2017-08-10", "2017-08-11", 42, 16).must_equal false + room.reserve_room("2018-08-10", "2018-08-11", 42, 16).must_equal false - check_in_str2 = "2017-09-28" - check_out_str2 = "2017-10-1" + check_in_str2 = "2018-09-28" + check_out_str2 = "2018-10-1" room.reserve_room(check_in_str2, check_out_str2, 8, 23) (Date.parse(check_in_str2)...Date.parse(check_out_str2)).each do |date| room.all_dates.must_include date end + end + + it "Raises an error when we try to book a room with a check-in or check-out date earlier than today" do + room = Hotel::Room.new(123) + check_in_str = "2016-08-09" + check_out_str = "2016-08-12" + proc { room.reserve_room(check_in_str, check_out_str, 1, 13)}.must_raise ArgumentError end - it "doesn't accept dates that are earlier than today's date" do + it "raises an error if the check-in or check-out date is invalidt" do + room = Hotel::Room.new(123) + check_in_str = "February 30, 2018" + check_out_str = "February 31, 2018" + + proc { room.reserve_room(check_in_str, check_out_str, 1, 13)}.must_raise ArgumentError end From f60aab0e18e8da9e67563095c0ab9ef5653cdde8 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Thu, 7 Sep 2017 10:26:34 -0700 Subject: [PATCH 10/27] Added a Room helper method, available_all_days?, which will be used to help return a list of all rooms available for a date range; passes a basic test that it will return the correct Boolean value --- lib/Room.rb | 19 ++++++++++++++++++- specs/Room_spec.rb | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/lib/Room.rb b/lib/Room.rb index 92a646317..4ca323e3a 100644 --- a/lib/Room.rb +++ b/lib/Room.rb @@ -35,6 +35,10 @@ def reserve_room(check_in_str,check_out_str,reservation_id, guest_id) raise ArgumentError.new("Please provide a valid date") end + if check_out < check_in + raise ArgumentError.new("Invalid Date Range: Check out date is earlier than check-in date.") + end + (check_in...check_out).each do |date| return false if @all_dates.include?(date) end @@ -71,6 +75,18 @@ def self.find_by_id(room_id) raise ArgumentError.new "Sorry, we don't have a room matching that ID number." end + + def available_all_days?(check_in_str, check_out_str) + check_in = Date.parse(check_in_str) + check_out = Date.parse(check_out_str) + + (check_in...check_out).each do |date| + return false if @all_dates.include?(date) + end + + return true + end + end end @@ -83,9 +99,10 @@ def self.find_by_id(room_id) # def available?(date_str) # #date format is year, month, day # date = Date.parse(date_str) -# return false if @reserv_id_and_dates.values.include?(date) +# return false if @all_dates.include?(date) # return true # end + # # def available_all_days?(check_in_str, check_out_str) # check_in = Date.parse(check_in_str) diff --git a/specs/Room_spec.rb b/specs/Room_spec.rb index b450500f4..fe5e805ff 100644 --- a/specs/Room_spec.rb +++ b/specs/Room_spec.rb @@ -59,7 +59,7 @@ proc { room.reserve_room(check_in_str, check_out_str, 1, 13)}.must_raise ArgumentError end - it "raises an error if the check-in or check-out date is invalidt" do + it "raises an error if the check-in or check-out date is invalid" do room = Hotel::Room.new(123) check_in_str = "February 30, 2018" check_out_str = "February 31, 2018" @@ -68,6 +68,14 @@ end + it "raises an error if the check-out dates is earlier than the check-in date" do + room = Hotel::Room.new(123) + check_in_str = "March 3, 2018" + check_out_str = "February 20, 2018" + + proc { room.reserve_room(check_in_str, check_out_str, 1, 13)}.must_raise ArgumentError + end + end #end reserve_room describe "self.all" do @@ -89,5 +97,36 @@ end #end self.all + describe "available_all_days?" do + it "returns the correct Boolean value" do + room1 = Hotel::Room.all[0] + + check_in = "2018-03-14" + check_out = "2018-03-18" + + room1.available_all_days?(check_in, check_out).must_equal true + room1.available_all_days?(check_in, check_out).must_be_instance_of TrueClass + + room1.reserve_room(check_in, check_out, 1, 2) + + check_in2 = "2018-03-16" + check_out2= "2018-03-17" + + room1.available_all_days?(check_in2, check_out2).must_equal false + room1.available_all_days?(check_in2, check_out2).must_be_instance_of FalseClass + + #### can make reservations that check-in on the same day that somebody checks out + check_in3 = "2018-03-18" + check_out3 = "2018-03-21" + + room1.available_all_days?(check_in3, check_out3).must_equal true + room1.available_all_days?(check_in3, check_out3).must_be_instance_of TrueClass + + end + + + + end #end available_all_days + end #end Hotel::Room class tests From 107fd3a780fc9b2c6b679713cfd9da7fb979e5d0 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Thu, 7 Sep 2017 16:31:06 -0700 Subject: [PATCH 11/27] can view a list of available rooms for a given date range and reserve an available room for a given date range. passes basic tests. design notes for possible refactoring included --- lib/Booking.rb | 27 ++++++++++---------- specs/Booking_spec.rb | 58 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 15 deletions(-) diff --git a/lib/Booking.rb b/lib/Booking.rb index 7ea21c2c6..9375a910a 100644 --- a/lib/Booking.rb +++ b/lib/Booking.rb @@ -4,6 +4,10 @@ require_relative 'Reservation' require_relative 'Room' +#TODO 09/07/2017:Design logic: Rooms have reservations, have dates, BUT CURRENTLY, Rooms store reservations and all dates on which they are reserved, and that is used to check quickly what rooms are available. +#Rooms also store a hash of Reservation id keys, with their corresponding dates as values, which seems superfluous. RECONSIDER THIS DESIGN. Should Rooms hold Reservation objects only? Reservation objects and dates reserved? maybe just reservation ids and dates? Maybe just reservation ids and helper method that will retrieve the reservation as needed? Think through + + module Hotel # NUMBER_OF_ROOMS = 20 ### might not want to use constant, especially if we have subclasses of rooms (by type), and each room subclass might have a different number. may best be a constant defined by class/subclass @@ -16,6 +20,15 @@ def initialize # do we want to initialize with hotel name? end + def available_rooms(check_in,check_out) + #check_in and #check_out are strings + #TODO: below + # confirm check_out date availability logic + #error handling + #message if no rooms are available? + @all_rooms.select {|room| room.available_all_days?(check_in, check_out)} + end + def make_reservation(guest_id, check_in,check_out,room_id) reservation = Hotel::Reservation.new(guest_id, check_in,check_out,room_id) @@ -45,17 +58,3 @@ def find_res_by_date(date_str) # binding.pry #########WAVE 2 ##### - -# def available_rooms(check_in,check_out) -# # confirm check_out date availability logic -# available_rooms = [] -# -# candidates = @all_rooms.select {|room| room.available?(check_in) && room.available?(check_out)} -# -# candidates.each do |room| -# available_rooms << room if room.available_all_days?(check_in, check_out) -# end -# -# return available_rooms if available_rooms.count > 0 -# return false -# end diff --git a/specs/Booking_spec.rb b/specs/Booking_spec.rb index ae20f2914..7aa2f1e01 100644 --- a/specs/Booking_spec.rb +++ b/specs/Booking_spec.rb @@ -37,5 +37,61 @@ p new_hotel.find_res_by_date("2018-03-21") end - end + end #end find_res_by_date + + + describe "available_rooms" do + before do + @new_hotel = Hotel::BookingProgram.new + @check_in = "June 1, 2018" + @check_out = "June 30, 2018" + @june_rooms = @new_hotel.available_rooms(@check_in, @check_out) + end + + it "returns an array of available rooms" do + + @june_rooms.must_be_instance_of Array + @june_rooms.count.must_equal 20 + @june_rooms.each do |room| + room.must_be_instance_of Hotel::Room + end + end + + it "updates correctly when all rooms are reserved" do + @new_hotel.all_rooms.each do |room| + guest_idx = 1 + res_idx = 10 + room.reserve_room(@check_in, @check_out, res_idx, guest_idx) + + guest_idx +=1 + res_idx +=1 + end + + updated_june_rooms= @new_hotel.available_rooms(@check_in, @check_out) + + updated_june_rooms.count.must_equal 0 + updated_june_rooms.must_be_instance_of Array + + end + + it "shows the correct number when all but one room are reserved" do + @new_hotel.all_rooms[1..-1].each do |room| + guest_idx = 1 + res_idx = 10 + room.reserve_room(@check_in, @check_out, res_idx, guest_idx) + + guest_idx +=1 + res_idx +=1 + end + + binding.pry + + updated_june_rooms= @new_hotel.available_rooms(@check_in, @check_out) + + updated_june_rooms.count.must_equal 1 + updated_june_rooms.must_be_instance_of Array + end + + end #end available_rooms + end From 8d8ca89f5b7fab999c9686f2cf09e6973bd2e554 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Thu, 7 Sep 2017 17:01:16 -0700 Subject: [PATCH 12/27] Refactored reservations and making reservations to have guest_id as an optional requirement --- lib/Booking.rb | 15 +++++++++++++-- lib/Reservation.rb | 15 ++------------- specs/Booking_spec.rb | 12 +++++------- specs/Reservation_spec.rb | 8 ++++---- 4 files changed, 24 insertions(+), 26 deletions(-) diff --git a/lib/Booking.rb b/lib/Booking.rb index 9375a910a..67d66f192 100644 --- a/lib/Booking.rb +++ b/lib/Booking.rb @@ -29,9 +29,9 @@ def available_rooms(check_in,check_out) @all_rooms.select {|room| room.available_all_days?(check_in, check_out)} end - def make_reservation(guest_id, check_in,check_out,room_id) + def make_reservation(check_in,check_out,room_id, guest_id=nil) - reservation = Hotel::Reservation.new(guest_id, check_in,check_out,room_id) + reservation = Hotel::Reservation.new(check_in,check_out,room_id, guest_id) reservation.id += 1 #something reservation.room.reserve_room(check_in,check_out,reservation.id, guest_id) @@ -50,6 +50,17 @@ def find_res_by_date(date_str) #self.all.select {|reservation| reservation.room.all_dates.include?(date_object)} end + # def find_res_by_guest(guest_id) + # end + # + + # + # def find_res_by_room(room_id) + # end + + #def find_res_by_id(reservation_id) + #end + end end diff --git a/lib/Reservation.rb b/lib/Reservation.rb index 2406bff7e..b90e51afa 100644 --- a/lib/Reservation.rb +++ b/lib/Reservation.rb @@ -8,12 +8,12 @@ class Reservation @@all_reservations = [] - def initialize(guest, check_in,check_out,room_id) + def initialize(check_in,check_out,room_id, guest = nil) @id = 1 - @guest = guest #Optional- create guest object @check_in = Date.parse(check_in) #ruby Date object @check_out = Date.parse(check_out) #ruby Date object @room= Hotel::Room.find_by_id(room_id) # later, this will be a room object assigned via namespacing method Hotel::Room.find_by(room_id) + @guest = guest #Optional- create guest object @totalcost = 200 end #end initialize @@ -30,17 +30,6 @@ def cost return @totalcost end - # def self.find_by_guest(guest_id) - # end - # - - # - # def self.find_by_room(room_id) - # end - - #def self.find_by_id(reservation_id) - #end - end end diff --git a/specs/Booking_spec.rb b/specs/Booking_spec.rb index 7aa2f1e01..78c9351c5 100644 --- a/specs/Booking_spec.rb +++ b/specs/Booking_spec.rb @@ -19,15 +19,15 @@ it "Returns an array of Reservation objects" do new_hotel = Hotel::BookingProgram.new - new_hotel.make_reservation(1, "2018-03-14", "2018-04-16", 3) + new_hotel.make_reservation("2018-03-14", "2018-04-16", 3, 1) - new_hotel.make_reservation(2, "2018-03-14", "2018-04-16", 5) + new_hotel.make_reservation("2018-03-14", "2018-04-16", 5, 2) - new_hotel.make_reservation(3, "2018-02-02", "2018-02-08", 18) + new_hotel.make_reservation("2018-02-02", "2018-02-08", 18, 3) - new_hotel.make_reservation(5, "2018-12-08", "2018-12-10", 7) + new_hotel.make_reservation("2018-12-08", "2018-12-10", 7, 5) - new_hotel.make_reservation(4, "2018-03-21", "2018-03-22", 15) + new_hotel.make_reservation("2018-03-21", "2018-03-22", 15, 4) new_hotel.find_res_by_date("2018-03-21").must_be_instance_of Array @@ -84,8 +84,6 @@ res_idx +=1 end - binding.pry - updated_june_rooms= @new_hotel.available_rooms(@check_in, @check_out) updated_june_rooms.count.must_equal 1 diff --git a/specs/Reservation_spec.rb b/specs/Reservation_spec.rb index 67cb5b599..41a1a2210 100644 --- a/specs/Reservation_spec.rb +++ b/specs/Reservation_spec.rb @@ -6,13 +6,13 @@ proc {Hotel::Reservation.new}.must_raise ArgumentError proc {Hotel::Reservation.new("Jim Bob", "2018-07-01",5)}.must_raise ArgumentError - new_res = Hotel::Reservation.new("Jim Bob", "July 1", "2018-07-03", 5) + new_res = Hotel::Reservation.new("July 1", "2018-07-03", 5, "Jim Bob") new_res.must_be_instance_of Hotel::Reservation end it "creates a Reservation instance that allows us to read the id, guest, check-in date, check-out date, and room " do - read_res = Hotel::Reservation.new("Dale Cooper", "2018-07-01", "2018-07-03", 5) + read_res = Hotel::Reservation.new("2018-07-01", "2018-07-03", 5, "Dale Cooper") read_res.must_be_instance_of Hotel::Reservation [read_res.check_in, read_res.check_out].each do |date| @@ -42,11 +42,11 @@ describe "Cost" do it "Returns an integer value that is the total cost of the reservation" do - reservation = Hotel::Reservation.new(1,"2018-02-14", "2018-02-16",5) + reservation = Hotel::Reservation.new("2018-02-14", "2018-02-16",5,1) reservation.cost.must_equal 400 - res2 = Hotel::Reservation.new(3, "2018-12-01", "2018-12-02", 17) + res2 = Hotel::Reservation.new("2018-12-01", "2018-12-02", 17,3) res2.cost.must_equal 200 end From b884efd4d3fc860509e746efce4183f3cb93196a Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Thu, 7 Sep 2017 22:51:36 -0700 Subject: [PATCH 13/27] added basic tests for making a reservation --- lib/Booking.rb | 17 +++++++++++++++++ specs/Booking_spec.rb | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/lib/Booking.rb b/lib/Booking.rb index 67d66f192..ccae7c3cc 100644 --- a/lib/Booking.rb +++ b/lib/Booking.rb @@ -3,10 +3,12 @@ require 'pry' require_relative 'Reservation' require_relative 'Room' +require_relative 'Block' #TODO 09/07/2017:Design logic: Rooms have reservations, have dates, BUT CURRENTLY, Rooms store reservations and all dates on which they are reserved, and that is used to check quickly what rooms are available. #Rooms also store a hash of Reservation id keys, with their corresponding dates as values, which seems superfluous. RECONSIDER THIS DESIGN. Should Rooms hold Reservation objects only? Reservation objects and dates reserved? maybe just reservation ids and dates? Maybe just reservation ids and helper method that will retrieve the reservation as needed? Think through +## THINK THROUGH: Does a Room create a Reservation based on availability vs. does a Reservation, once created, reserve a room? module Hotel # NUMBER_OF_ROOMS = 20 ### might not want to use constant, especially if we have subclasses of rooms (by type), and each room subclass might have a different number. may best be a constant defined by class/subclass @@ -20,6 +22,7 @@ def initialize # do we want to initialize with hotel name? end + ####should this be a Room, self.all method def available_rooms(check_in,check_out) #check_in and #check_out are strings #TODO: below @@ -29,9 +32,23 @@ def available_rooms(check_in,check_out) @all_rooms.select {|room| room.available_all_days?(check_in, check_out)} end + ###should this be a Room method def make_reservation(check_in,check_out,room_id, guest_id=nil) reservation = Hotel::Reservation.new(check_in,check_out,room_id, guest_id) + reservation.id = (@all_reservations.count + 1) #something + + reservation.room.reserve_room(check_in,check_out,reservation.id, guest_id) + + @all_reservations << reservation + + end + + def make_block(check_in,check_out,room_ids,discounted_rate,block_id) + + raise ArgumentError.new("Number of rooms in a block must be 5 or under") if room_ids.count > 5 + + reservation = Hotel::Block.new(check_in,check_out,room_id, guest_id) reservation.id += 1 #something reservation.room.reserve_room(check_in,check_out,reservation.id, guest_id) diff --git a/specs/Booking_spec.rb b/specs/Booking_spec.rb index 78c9351c5..09ba82384 100644 --- a/specs/Booking_spec.rb +++ b/specs/Booking_spec.rb @@ -39,6 +39,25 @@ end end #end find_res_by_date + describe "make reservation" do + it "reserves a room and makes a reservation object " do + new_hotel = Hotel::BookingProgram.new + + new_hotel.make_reservation("2018-03-14", "2018-03-16", 3, 1) + + new_reservation = new_hotel.all_reservations[0] + + + + new_reservation.must_be_instance_of Hotel::Reservation + new_reservation.id.must_equal 1 + (Date.parse("2018-03-14")...Date.parse("2018-03-16")).to_a.each do |date| + new_reservation.room.all_dates.must_include date + end + + end + end + describe "available_rooms" do before do From 420fb74e0c9827696f7cbfa6052dbaf78d815482 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Thu, 7 Sep 2017 22:54:08 -0700 Subject: [PATCH 14/27] Created Block class, which currently inherits from Reservation class. May change. Passing basic tests --- lib/Block.rb | 31 +++++++++++++++++++++++++++++++ specs/Block_spec.rb | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 lib/Block.rb create mode 100644 specs/Block_spec.rb diff --git a/lib/Block.rb b/lib/Block.rb new file mode 100644 index 000000000..18a7268e3 --- /dev/null +++ b/lib/Block.rb @@ -0,0 +1,31 @@ +require 'pry' + +require_relative 'Booking' + +module Hotel + class Block < Hotel::Reservation #or is it Reservation + attr_accessor :id, :guest, :check_in, :check_out, :rooms + attr_reader :discounted_rate + + def initialize(check_in,check_out,room_ids,discounted_rate,block_id) + @check_in = Date.parse(check_in) #ruby Date object + @check_out = Date.parse(check_out) #ruby Date object + @totalcost = discounted_rate + @rooms = [] + @discounted_rate = discounted_rate + room_ids.each do |id| + room = Hotel::Room.find_by_id(id) + # room.reserve_room(check_in,check_out,@id) + @rooms << room + end + + @id = block_id + end + + def cost + num_nights_charged * @discounted_rate + end + + end + +end diff --git a/specs/Block_spec.rb b/specs/Block_spec.rb new file mode 100644 index 000000000..b459dc80e --- /dev/null +++ b/specs/Block_spec.rb @@ -0,0 +1,36 @@ +require_relative 'spec_helper' + +describe "Hotel::Block class " do + describe "initialize" do + it "initalizes" do + check_in_str = "2018-10-03" + check_out_str = "2018-10-06" + room_ids = [1,2,3] + block_id = "Amy's Party" + discounted_rate = 5 + new_block = Hotel::Block.new(check_in_str, check_out_str,room_ids,discounted_rate,block_id) + + new_block.must_be_instance_of Hotel::Block + # new_block.rooms.must_be_instance_of Array + # new_block.rooms.each do |room| + # room.must_be_instance_of Hotel::Room + # end + + end + + it "correctly inherits the num_nights_charged method from the Hotel::Reservation class" do + block1 = Hotel::Block.new("2018-02-14", "2018-02-16",[11,12,13],5,1) + + block1.num_nights_charged.must_equal 2 + end + + it "calculates cost with a discounted rate" do + block1 = Hotel::Block.new("2018-02-14", "2018-02-16",[11,12,13],5,1) + block1.cost.must_equal 10 + + block2 = Hotel::Block.new("2018-12-01", "2018-12-02",[17,18],5,14) + + block2.cost.must_equal 5 + end + end +end From 5de0cd98b0fb53ce95bfff3ebf8ea76893bc62c8 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Thu, 7 Sep 2017 23:47:41 -0700 Subject: [PATCH 15/27] Created make_block method in BookingProgram and block_room method in Room class, passing basic tests --- lib/Booking.rb | 21 ++++++++++------- lib/Room.rb | 52 +++++++++++++++++++++++++++++++------------ specs/Booking_spec.rb | 29 +++++++++++++++++++++--- specs/Room_spec.rb | 25 +++++++++++++++++++++ 4 files changed, 102 insertions(+), 25 deletions(-) diff --git a/lib/Booking.rb b/lib/Booking.rb index ccae7c3cc..2989efa50 100644 --- a/lib/Booking.rb +++ b/lib/Booking.rb @@ -14,11 +14,12 @@ module Hotel # NUMBER_OF_ROOMS = 20 ### might not want to use constant, especially if we have subclasses of rooms (by type), and each room subclass might have a different number. may best be a constant defined by class/subclass class BookingProgram - attr_reader :all_rooms, :all_reservations + attr_reader :all_rooms, :all_reservations, :all_blocks def initialize # do we want to initialize with hotel name? @all_rooms = Hotel::Room.all # returns an array or hash of Room objects @all_reservations = [] + @all_blocks = [] end @@ -35,8 +36,9 @@ def available_rooms(check_in,check_out) ###should this be a Room method def make_reservation(check_in,check_out,room_id, guest_id=nil) - reservation = Hotel::Reservation.new(check_in,check_out,room_id, guest_id) - reservation.id = (@all_reservations.count + 1) #something + reservation_id = (@all_reservations.count + 1) #something + reservation = Hotel::Reservation.new(check_in,check_out,room_id, reservation_id, guest_id) + reservation.room.reserve_room(check_in,check_out,reservation.id, guest_id) @@ -44,16 +46,19 @@ def make_reservation(check_in,check_out,room_id, guest_id=nil) end - def make_block(check_in,check_out,room_ids,discounted_rate,block_id) + def make_block(check_in,check_out,room_ids,discounted_rate) raise ArgumentError.new("Number of rooms in a block must be 5 or under") if room_ids.count > 5 - reservation = Hotel::Block.new(check_in,check_out,room_id, guest_id) - reservation.id += 1 #something + block_id = @all_blocks.count + 1 - reservation.room.reserve_room(check_in,check_out,reservation.id, guest_id) + block = Hotel::Block.new(check_in,check_out,room_ids,discounted_rate,block_id) - @all_reservations << reservation + block.rooms.each do |room| + room.block_room(check_in,check_out,block_id) + end + + @all_blocks << block end diff --git a/lib/Room.rb b/lib/Room.rb index 4ca323e3a..79c83e888 100644 --- a/lib/Room.rb +++ b/lib/Room.rb @@ -5,7 +5,7 @@ module Hotel class Room - attr_reader :id, :nightly_rate, :type, :reserv_id_and_dates, :all_dates + attr_reader :id, :nightly_rate, :type, :reserv_id_and_dates, :all_dates, :block_id_and_dates # :status @@total_num_rooms = 20 @@ -13,31 +13,22 @@ class Room def initialize(id_number, nightly_rate = 200) @id = id_number @nightly_rate = nightly_rate - @type = :standard + @type = :standard # is this necessary @reserv_id_and_dates = {} # holds all reservations, a hash with reservation ids as keys and values as the date range of the reservation ### check-out date should not be included + @block_id_and_dates = {} @all_dates = [] # @status = :available #not sure if status is needed anymore.maybe a method, available? end - def reserve_room(check_in_str,check_out_str,reservation_id, guest_id) + def reserve_room(check_in_str,check_out_str,reservation_id, guest_id=nil) check_in = Date.parse(check_in_str) check_out = Date.parse(check_out_str) + check_valid_dates(check_in,check_out) - if check_in < Date.today || check_out < Date.today - raise ArgumentError.new("Can't make reservations for days earlier than today") - end - - if check_in.class != Date ||check_out.class != Date - raise ArgumentError.new("Please provide a valid date") - end - - if check_out < check_in - raise ArgumentError.new("Invalid Date Range: Check out date is earlier than check-in date.") - end (check_in...check_out).each do |date| return false if @all_dates.include?(date) @@ -55,6 +46,24 @@ def reserve_room(check_in_str,check_out_str,reservation_id, guest_id) end + def block_room(check_in_str,check_out_str,block_id) + check_in = Date.parse(check_in_str) + check_out = Date.parse(check_out_str) + + check_valid_dates(check_in,check_out) + + (check_in...check_out).each do |date| + return false if @all_dates.include?(date) + end + + @block_id_and_dates[block_id] = [] + + (check_in...check_out).each do |date| + @all_dates << date + end + + end + def self.all i = 1 all_rooms = [] @@ -87,6 +96,21 @@ def available_all_days?(check_in_str, check_out_str) return true end + def check_valid_dates(check_in, check_out) + if check_in < Date.today || check_out < Date.today + raise ArgumentError.new("Can't make reservations for days earlier than today") + end + + if check_in.class != Date ||check_out.class != Date + raise ArgumentError.new("Please provide a valid date") + end + + if check_out < check_in + raise ArgumentError.new("Invalid Date Range: Check out date is earlier than check-in date.") + end + + end + end end diff --git a/specs/Booking_spec.rb b/specs/Booking_spec.rb index 09ba82384..7a4c4f836 100644 --- a/specs/Booking_spec.rb +++ b/specs/Booking_spec.rb @@ -40,7 +40,7 @@ end #end find_res_by_date describe "make reservation" do - it "reserves a room and makes a reservation object " do + it "reserves a Room and makes a Reservation object " do new_hotel = Hotel::BookingProgram.new new_hotel.make_reservation("2018-03-14", "2018-03-16", 3, 1) @@ -48,12 +48,35 @@ new_reservation = new_hotel.all_reservations[0] - new_reservation.must_be_instance_of Hotel::Reservation new_reservation.id.must_equal 1 (Date.parse("2018-03-14")...Date.parse("2018-03-16")).to_a.each do |date| new_reservation.room.all_dates.must_include date - end + end + + end + end + + describe "make block" do + it "creates a Block and reserves a room" do + #note, need to fix: it shouldn't reserve room officially, but should be "Blocked off" test for this when the functionality is made + + new_hotel = Hotel::BookingProgram.new + + new_hotel.make_block("2018-03-14", "2018-03-16",[18,19,20], 2) + + new_block = new_hotel.all_blocks[0] + + + new_block.must_be_instance_of Hotel::Block + new_block.id.must_equal 1 + + new_block.rooms.each do |room| + (Date.parse("2018-03-14")...Date.parse("2018-03-16")).to_a.each do |date| + room.all_dates.must_include date #fix this logic later + end + end + end end diff --git a/specs/Room_spec.rb b/specs/Room_spec.rb index fe5e805ff..99e709e40 100644 --- a/specs/Room_spec.rb +++ b/specs/Room_spec.rb @@ -128,5 +128,30 @@ end #end available_all_days + describe "block room" do + it "can block a room if given the check-in/out date and block id so that it is unavailable to reserve via regular reservations" do + room = Hotel::Room.new(666) + check_in_str = "2018-08-09" + check_out_str = "2018-08-12" + block_id = 3 + + room.block_room(check_in_str, check_out_str, block_id) + + (Date.parse(check_in_str)...Date.parse(check_out_str)).each do |date| + room.all_dates.must_include date + end + + room.reserve_room("2018-08-10", "2018-08-11", 42, 16).must_equal false + + check_in_str2 = "2018-09-28" + check_out_str2 = "2018-10-1" + + room.reserve_room(check_in_str2, check_out_str2, 8, 23) + (Date.parse(check_in_str2)...Date.parse(check_out_str2)).each do |date| + room.all_dates.must_include date + end + end + end + end #end Hotel::Room class tests From 729b56f28cfe7ddc5d698f069f834a44a061f749 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Thu, 7 Sep 2017 23:49:30 -0700 Subject: [PATCH 16/27] made the reservation id a required argument to initialize a Reservation object, and changed the order of the initialize arguments --- lib/Reservation.rb | 17 ++++++++++------- specs/Reservation_spec.rb | 6 +++--- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/Reservation.rb b/lib/Reservation.rb index b90e51afa..6a21b3320 100644 --- a/lib/Reservation.rb +++ b/lib/Reservation.rb @@ -3,18 +3,18 @@ module Hotel class Reservation - attr_reader :guest, :check_in, :check_out, :room - attr_accessor :all_reservations, :id + attr_accessor :id, :guest, :check_in, :check_out, :room + attr_reader :all_reservations, :type @@all_reservations = [] - def initialize(check_in,check_out,room_id, guest = nil) - @id = 1 + def initialize(check_in,check_out,room_id, res_id, guest = nil, type = :standard) + @id = res_id @check_in = Date.parse(check_in) #ruby Date object @check_out = Date.parse(check_out) #ruby Date object @room= Hotel::Room.find_by_id(room_id) # later, this will be a room object assigned via namespacing method Hotel::Room.find_by(room_id) @guest = guest #Optional- create guest object - @totalcost = 200 + @type = type end #end initialize @@ -26,8 +26,11 @@ def self.all #returns array end def cost - @totalcost = (check_out.mjd - check_in.mjd)* @room.nightly_rate - return @totalcost + num_nights_charged * @room.nightly_rate + end + + def num_nights_charged + (check_out.mjd - check_in.mjd) end end diff --git a/specs/Reservation_spec.rb b/specs/Reservation_spec.rb index 41a1a2210..150659069 100644 --- a/specs/Reservation_spec.rb +++ b/specs/Reservation_spec.rb @@ -6,13 +6,13 @@ proc {Hotel::Reservation.new}.must_raise ArgumentError proc {Hotel::Reservation.new("Jim Bob", "2018-07-01",5)}.must_raise ArgumentError - new_res = Hotel::Reservation.new("July 1", "2018-07-03", 5, "Jim Bob") + new_res = Hotel::Reservation.new("July 1", "2018-07-03", 5, 14, "Jim Bob") new_res.must_be_instance_of Hotel::Reservation end it "creates a Reservation instance that allows us to read the id, guest, check-in date, check-out date, and room " do - read_res = Hotel::Reservation.new("2018-07-01", "2018-07-03", 5, "Dale Cooper") + read_res = Hotel::Reservation.new("2018-07-01", "2018-07-03", 5,100, "Dale Cooper") read_res.must_be_instance_of Hotel::Reservation [read_res.check_in, read_res.check_out].each do |date| @@ -21,7 +21,7 @@ read_res.check_in.day.must_equal 1 read_res.check_out.day.must_equal 3 - + read_res.id.must_equal 100 read_res.room.id.must_equal 5 read_res.guest.must_equal "Dale Cooper" end From b56ae49c9d2ddbd8a34c2f8dc758fc1e331272b8 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Thu, 7 Sep 2017 23:50:14 -0700 Subject: [PATCH 17/27] Added Block to required files --- specs/spec_helper.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/spec_helper.rb b/specs/spec_helper.rb index 6f9528f7c..2f7281073 100644 --- a/specs/spec_helper.rb +++ b/specs/spec_helper.rb @@ -7,5 +7,6 @@ require_relative '../lib/Reservation' require_relative '../lib/Room' require_relative '../lib/Guest' +require_relative '../lib/Block' Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new From 57c76a92b0acee82c7f655b2ed963b145f773543 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Fri, 8 Sep 2017 01:33:30 -0700 Subject: [PATCH 18/27] Added new BlockReservation subclass of Reservation. Block is now an independent class. First attempt at implementing logic for making Block reservations, passing --- lib/Block.rb | 8 ++---- lib/BlockReservation.rb | 21 ++++++++++++++++ lib/Booking.rb | 46 ++++++++++++++++++++++++++++++++-- lib/Reservation.rb | 5 ++-- specs/BlockReservation_spec.rb | 46 ++++++++++++++++++++++++++++++++++ specs/Block_spec.rb | 15 ----------- specs/Booking_spec.rb | 14 +++++------ specs/Reservation_spec.rb | 5 ++-- specs/spec_helper.rb | 1 + 9 files changed, 125 insertions(+), 36 deletions(-) create mode 100644 lib/BlockReservation.rb create mode 100644 specs/BlockReservation_spec.rb diff --git a/lib/Block.rb b/lib/Block.rb index 18a7268e3..f90e068ca 100644 --- a/lib/Block.rb +++ b/lib/Block.rb @@ -3,14 +3,13 @@ require_relative 'Booking' module Hotel - class Block < Hotel::Reservation #or is it Reservation + class Block attr_accessor :id, :guest, :check_in, :check_out, :rooms attr_reader :discounted_rate def initialize(check_in,check_out,room_ids,discounted_rate,block_id) @check_in = Date.parse(check_in) #ruby Date object @check_out = Date.parse(check_out) #ruby Date object - @totalcost = discounted_rate @rooms = [] @discounted_rate = discounted_rate room_ids.each do |id| @@ -20,10 +19,7 @@ def initialize(check_in,check_out,room_ids,discounted_rate,block_id) end @id = block_id - end - - def cost - num_nights_charged * @discounted_rate + @all_block_reservations = [] end end diff --git a/lib/BlockReservation.rb b/lib/BlockReservation.rb new file mode 100644 index 000000000..5f9db745f --- /dev/null +++ b/lib/BlockReservation.rb @@ -0,0 +1,21 @@ +require_relative 'Block' +require_relative 'Reservation' +require_relative 'Booking' + +module Hotel + class BlockReservation < Hotel::Reservation + def initialize(check_in,check_out,room_id, b_res_id, block_discount, block_id,guest = nil) + super(check_in,check_out,room_id, b_res_id,block_discount, guest = nil) + #how do I get the discounted_rate? must incorpo + @discounted_rate = block_discount + @block_id = block_id + @type= :block + end #end initialize + + def cost + num_nights_charged * @discounted_rate + end + end +end + +#can I additional parameter block_id, and still use super to inherit from Reservation diff --git a/lib/Booking.rb b/lib/Booking.rb index 2989efa50..3c79cf949 100644 --- a/lib/Booking.rb +++ b/lib/Booking.rb @@ -34,12 +34,26 @@ def available_rooms(check_in,check_out) end ###should this be a Room method - def make_reservation(check_in,check_out,room_id, guest_id=nil) + def make_reservation(check_in,check_out,room_id, block_id = nil, guest_id=nil) reservation_id = (@all_reservations.count + 1) #something - reservation = Hotel::Reservation.new(check_in,check_out,room_id, reservation_id, guest_id) + if block_id + #TODO: think about whether or not to have a separate block reservation id logic and whether or not to store block reservations in the same place as all reservations AND store them separately, or store them in one place (either all reservations or Block reservations) + raise ArgumentError.new("This block doesn't exist") if !(find_block_by_id(block_id)) + block= find_block_by_id(block_id) + block_discount = block.discounted_rate + + #TODO: IRON OUT and TEST block reservation constraints: check in and check out MUST be that of the BLOCK check_in/Check_out dates + block_check_in = block.check_in.to_s + block_check_out= block.check_out.to_s + reservation = Hotel::BlockReservation.new(block_check_in,block_check_out,room_id, reservation_id, block_discount, block_id) + else + reservation = Hotel::Reservation.new(check_in,check_out,room_id, reservation_id,block_id) + end + + #TODO: How to incorporate reserve_room logic for Block Reservations reservation.room.reserve_room(check_in,check_out,reservation.id, guest_id) @all_reservations << reservation @@ -62,6 +76,24 @@ def make_block(check_in,check_out,room_ids,discounted_rate) end + # def make_block_res(check_in,check_out,room_id, block_id, type = :block, guest_id=nil) + # room= Hotel::Room.find_by_id(room_id) + # block = find_block_by_id(block_id) + # + # raise ArgumentError.new("Error: No block matching that ID number") if !(block) + # raise ArgumentError.new("This room isn't included in your block") if !(room.block_id_and_res_dates.keys.include?(block_id)) + # + # reservation_id = (@all_reservations.count + 1) #something + # reservation = Hotel::Reservation.new(check_in,check_out,room_id, reservation_id,type = :block,guest_id) + # + # + # reservation.room.reserve_room(check_in,check_out,reservation.id, guest_id) + # + # @all_reservations << reservation + # + # + # end + def find_res_by_date(date_str) date_object= Date.parse(date_str) reserved_on_date = [] @@ -72,6 +104,16 @@ def find_res_by_date(date_str) #self.all.select {|reservation| reservation.room.all_dates.include?(date_object)} end + def find_block_by_id(block_id) + @all_blocks.each do |block| + return block if block.id == block_id + end + + return false + end + + + # def find_res_by_guest(guest_id) # end # diff --git a/lib/Reservation.rb b/lib/Reservation.rb index 6a21b3320..d2e608a7c 100644 --- a/lib/Reservation.rb +++ b/lib/Reservation.rb @@ -8,13 +8,14 @@ class Reservation @@all_reservations = [] - def initialize(check_in,check_out,room_id, res_id, guest = nil, type = :standard) + def initialize(check_in,check_out,room_id, res_id, discounted_rate = nil, guest = nil) @id = res_id @check_in = Date.parse(check_in) #ruby Date object @check_out = Date.parse(check_out) #ruby Date object @room= Hotel::Room.find_by_id(room_id) # later, this will be a room object assigned via namespacing method Hotel::Room.find_by(room_id) @guest = guest #Optional- create guest object - @type = type + @discounted_rate = discounted_rate + @type= :standard end #end initialize diff --git a/specs/BlockReservation_spec.rb b/specs/BlockReservation_spec.rb new file mode 100644 index 000000000..9ca5fc7fd --- /dev/null +++ b/specs/BlockReservation_spec.rb @@ -0,0 +1,46 @@ +require 'date' +require 'pry' +require_relative 'spec_helper' + +describe "Hotel::BlockReservation class" do + describe "initialize" do + it "initalizes" do + check_in_str = "2018-10-03" + check_out_str = "2018-10-06" + room_id = 1 + b_res_id = 14 + discounted_rate = 5 + block_id = 42 + new_block_res = Hotel::BlockReservation.new(check_in_str, check_out_str,room_id,b_res_id,discounted_rate, block_id) + + new_block_res.must_be_instance_of Hotel::BlockReservation + # new_block.rooms.must_be_instance_of Array + # new_block.rooms.each do |room| + # room.must_be_instance_of Hotel::Room + # end + + end + end + + xdescribe "num_nights_charged" do + + it "correctly inherits the num_nights_charged method from the Hotel::Reservation class" do + blockres1 = Hotel::BlockReservation.new("2018-02-14", "2018-02-16",3,14,5) + + blockres1.num_nights_charged.must_equal 2 + end + end + + xdescribe "cost" do + it "calculates cost with a discounted rate" do + discounted_rate = 5 + blockres1 = Hotel::BlockReservation.new("2018-02-14", "2018-02-16",14,42,discounted_rate) + blockres1.cost.must_equal 10 + + blockres2 = Hotel::BlockReservation.new("2018-12-01", "2018-12-02",1,5,discounted_rate) + + blockres2.cost.must_equal 5 + end + end + +end diff --git a/specs/Block_spec.rb b/specs/Block_spec.rb index b459dc80e..7761f000e 100644 --- a/specs/Block_spec.rb +++ b/specs/Block_spec.rb @@ -17,20 +17,5 @@ # end end - - it "correctly inherits the num_nights_charged method from the Hotel::Reservation class" do - block1 = Hotel::Block.new("2018-02-14", "2018-02-16",[11,12,13],5,1) - - block1.num_nights_charged.must_equal 2 - end - - it "calculates cost with a discounted rate" do - block1 = Hotel::Block.new("2018-02-14", "2018-02-16",[11,12,13],5,1) - block1.cost.must_equal 10 - - block2 = Hotel::Block.new("2018-12-01", "2018-12-02",[17,18],5,14) - - block2.cost.must_equal 5 - end end end diff --git a/specs/Booking_spec.rb b/specs/Booking_spec.rb index 7a4c4f836..aa946628a 100644 --- a/specs/Booking_spec.rb +++ b/specs/Booking_spec.rb @@ -19,23 +19,21 @@ it "Returns an array of Reservation objects" do new_hotel = Hotel::BookingProgram.new - new_hotel.make_reservation("2018-03-14", "2018-04-16", 3, 1) + new_hotel.make_reservation("2018-03-14", "2018-04-16", 3) - new_hotel.make_reservation("2018-03-14", "2018-04-16", 5, 2) + new_hotel.make_reservation("2018-03-14", "2018-04-16", 5) - new_hotel.make_reservation("2018-02-02", "2018-02-08", 18, 3) + new_hotel.make_reservation("2018-02-02", "2018-02-08", 18) - new_hotel.make_reservation("2018-12-08", "2018-12-10", 7, 5) + new_hotel.make_reservation("2018-12-08", "2018-12-10", 7) - new_hotel.make_reservation("2018-03-21", "2018-03-22", 15, 4) + new_hotel.make_reservation("2018-03-21", "2018-03-22", 15) new_hotel.find_res_by_date("2018-03-21").must_be_instance_of Array new_hotel.find_res_by_date("2018-03-21").count.must_equal 3 - p new_hotel.find_res_by_date("2018-03-21") - end end #end find_res_by_date @@ -43,7 +41,7 @@ it "reserves a Room and makes a Reservation object " do new_hotel = Hotel::BookingProgram.new - new_hotel.make_reservation("2018-03-14", "2018-03-16", 3, 1) + new_hotel.make_reservation("2018-03-14", "2018-03-16", 3) new_reservation = new_hotel.all_reservations[0] diff --git a/specs/Reservation_spec.rb b/specs/Reservation_spec.rb index 150659069..7abd2864a 100644 --- a/specs/Reservation_spec.rb +++ b/specs/Reservation_spec.rb @@ -6,13 +6,13 @@ proc {Hotel::Reservation.new}.must_raise ArgumentError proc {Hotel::Reservation.new("Jim Bob", "2018-07-01",5)}.must_raise ArgumentError - new_res = Hotel::Reservation.new("July 1", "2018-07-03", 5, 14, "Jim Bob") + new_res = Hotel::Reservation.new("July 1", "2018-07-03", 5, 14) new_res.must_be_instance_of Hotel::Reservation end it "creates a Reservation instance that allows us to read the id, guest, check-in date, check-out date, and room " do - read_res = Hotel::Reservation.new("2018-07-01", "2018-07-03", 5,100, "Dale Cooper") + read_res = Hotel::Reservation.new("2018-07-01", "2018-07-03", 5,100) read_res.must_be_instance_of Hotel::Reservation [read_res.check_in, read_res.check_out].each do |date| @@ -23,7 +23,6 @@ read_res.check_out.day.must_equal 3 read_res.id.must_equal 100 read_res.room.id.must_equal 5 - read_res.guest.must_equal "Dale Cooper" end end #end initialize tests diff --git a/specs/spec_helper.rb b/specs/spec_helper.rb index 2f7281073..481a2a381 100644 --- a/specs/spec_helper.rb +++ b/specs/spec_helper.rb @@ -8,5 +8,6 @@ require_relative '../lib/Room' require_relative '../lib/Guest' require_relative '../lib/Block' +require_relative '../lib/BlockReservation' Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new From f4a8494e6dfac3a9f4cb94bebc8b3fcccc1f132a Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Fri, 8 Sep 2017 10:52:16 -0700 Subject: [PATCH 19/27] Added code and logic for handling block reservations, untested. --- lib/Booking.rb | 38 +++++++++++++++++++++++++++++++++++--- lib/Room.rb | 23 +++++++++++++++++++++-- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/lib/Booking.rb b/lib/Booking.rb index 3c79cf949..8e6a7ad8c 100644 --- a/lib/Booking.rb +++ b/lib/Booking.rb @@ -15,22 +15,27 @@ module Hotel class BookingProgram attr_reader :all_rooms, :all_reservations, :all_blocks + NUM_STANDARD_ROOMS = 20 + #NUM_OTHER_ROOMS = 0 def initialize # do we want to initialize with hotel name? @all_rooms = Hotel::Room.all # returns an array or hash of Room objects + # @all_rooms2 = Hotel::BookingProgram.setup_rooms @all_reservations = [] @all_blocks = [] end ####should this be a Room, self.all method - def available_rooms(check_in,check_out) + def available_rooms(check_in,check_out, block_id = nil) #check_in and #check_out are strings #TODO: below # confirm check_out date availability logic #error handling #message if no rooms are available? @all_rooms.select {|room| room.available_all_days?(check_in, check_out)} + + #if block_id end ###should this be a Room method @@ -40,21 +45,29 @@ def make_reservation(check_in,check_out,room_id, block_id = nil, guest_id=nil) if block_id #TODO: think about whether or not to have a separate block reservation id logic and whether or not to store block reservations in the same place as all reservations AND store them separately, or store them in one place (either all reservations or Block reservations) - raise ArgumentError.new("This block doesn't exist") if !(find_block_by_id(block_id)) block= find_block_by_id(block_id) + raise ArgumentError.new("This block doesn't exist") if !(find_block_by_id(block_id)) + block_discount = block.discounted_rate + block_room = Hotel::Room.find_by_id(room_id)#must be included in the block + + raise ArgumentError.new("This room is not in the block") if !(block.rooms.include?(block_room)) #TODO: IRON OUT and TEST block reservation constraints: check in and check out MUST be that of the BLOCK check_in/Check_out dates block_check_in = block.check_in.to_s block_check_out= block.check_out.to_s + + #TODO: Think about if we want to make a block reservation id a +1 count of all reservations, or have separate ids for blocks reservation = Hotel::BlockReservation.new(block_check_in,block_check_out,room_id, reservation_id, block_discount, block_id) else reservation = Hotel::Reservation.new(check_in,check_out,room_id, reservation_id,block_id) end #TODO: How to incorporate reserve_room logic for Block Reservations - reservation.room.reserve_room(check_in,check_out,reservation.id, guest_id) + reservation.room.reserve_room(check_in,check_out,reservation.id, guest_id) if reservation.type == :standard + + reservation.room.reserve_block_room(check_in,check_out,reservation.id, block_id, guest_id=nil) if reservation.type == :block @all_reservations << reservation @@ -104,6 +117,10 @@ def find_res_by_date(date_str) #self.all.select {|reservation| reservation.room.all_dates.include?(date_object)} end + def find_block_res_by_block_id(block_id,guest_id=nil ) + + end + def find_block_by_id(block_id) @all_blocks.each do |block| return block if block.id == block_id @@ -112,6 +129,21 @@ def find_block_by_id(block_id) return false end + # def self.setup_rooms + # i = 1 + # standard_rooms = [] + # + # until standard_rooms.count == NUM_STANDARD_ROOMS + # room = Hotel::Room.new(i) + # standard_rooms << room + # i += 1 + # end + # + # return standard_rooms + # end + + + # def find_res_by_guest(guest_id) diff --git a/lib/Room.rb b/lib/Room.rb index 79c83e888..60fa081d7 100644 --- a/lib/Room.rb +++ b/lib/Room.rb @@ -1,6 +1,7 @@ require 'pry' require 'date' require_relative 'Reservation' +require_relative 'BlockReservation' module Hotel @@ -16,7 +17,7 @@ def initialize(id_number, nightly_rate = 200) @type = :standard # is this necessary @reserv_id_and_dates = {} # holds all reservations, a hash with reservation ids as keys and values as the date range of the reservation ### check-out date should not be included - @block_id_and_dates = {} + @block_id_and_res_dates = {} @all_dates = [] # @status = :available #not sure if status is needed anymore.maybe a method, available? @@ -46,6 +47,24 @@ def reserve_room(check_in_str,check_out_str,reservation_id, guest_id=nil) end + def reserve_block_room(check_in_str,check_out_str,reservation_id, block_id, guest_id=nil) + check_in = Date.parse(check_in_str) + check_out = Date.parse(check_out_str) + + check_valid_dates(check_in,check_out) + + (check_in...check_out).each do |date| + raise ArgumentError.new("this room has already been reserved for these dates in this block") if @block_id_and_res_dates[block_id].include? + end + + (check_in...check_out).each do |date| + @block_id_and_res_dates[block_id]<< date + end + + + end + + def block_room(check_in_str,check_out_str,block_id) check_in = Date.parse(check_in_str) check_out = Date.parse(check_out_str) @@ -56,7 +75,7 @@ def block_room(check_in_str,check_out_str,block_id) return false if @all_dates.include?(date) end - @block_id_and_dates[block_id] = [] + @block_id_and_res_dates[block_id] = [] (check_in...check_out).each do |date| @all_dates << date From 3b43cc39872de988064e7360c5007e892af64ac7 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Fri, 8 Sep 2017 14:55:52 -0700 Subject: [PATCH 20/27] Major refactor- Reservations, BlockReservation, and Blocks all hold Room IDs only, not Room objects, for the purposes of figuring out method logic/figuring out how classes connect and effect each other. all tests passing; will probably change --- lib/Block.rb | 16 +++--- lib/BlockReservation.rb | 12 +++-- lib/Booking.rb | 96 +++++++++++++++++++++------------- lib/Reservation.rb | 10 ++-- lib/Room.rb | 12 ++++- specs/BlockReservation_spec.rb | 9 ++-- specs/Block_spec.rb | 8 +-- specs/Booking_spec.rb | 94 ++++++++++++++++++++++++++++++++- specs/Reservation_spec.rb | 2 +- specs/Room_spec.rb | 63 ++++++++++++++++++++++ 10 files changed, 253 insertions(+), 69 deletions(-) diff --git a/lib/Block.rb b/lib/Block.rb index f90e068ca..8146da5b2 100644 --- a/lib/Block.rb +++ b/lib/Block.rb @@ -1,22 +1,20 @@ require 'pry' -require_relative 'Booking' - module Hotel class Block - attr_accessor :id, :guest, :check_in, :check_out, :rooms + attr_accessor :id, :guest, :check_in, :check_out, :room_ids attr_reader :discounted_rate def initialize(check_in,check_out,room_ids,discounted_rate,block_id) @check_in = Date.parse(check_in) #ruby Date object @check_out = Date.parse(check_out) #ruby Date object - @rooms = [] + @room_ids = room_ids @discounted_rate = discounted_rate - room_ids.each do |id| - room = Hotel::Room.find_by_id(id) - # room.reserve_room(check_in,check_out,@id) - @rooms << room - end + # room_ids.each do |id| + # room = Hotel::BookingProgram.find_room_by_id(id) + # # room.reserve_room(check_in,check_out,@id) + # @rooms << room + # end @id = block_id @all_block_reservations = [] diff --git a/lib/BlockReservation.rb b/lib/BlockReservation.rb index 5f9db745f..fb37b8996 100644 --- a/lib/BlockReservation.rb +++ b/lib/BlockReservation.rb @@ -1,15 +1,19 @@ + require_relative 'Block' require_relative 'Reservation' require_relative 'Booking' module Hotel class BlockReservation < Hotel::Reservation - def initialize(check_in,check_out,room_id, b_res_id, block_discount, block_id,guest = nil) + attr_accessor :id, :guest, :check_in, :check_out, :room, :block_id + attr_reader :all_reservations, :type + + def initialize(check_in,check_out,room_id, b_res_id, block_discount,guest = nil) super(check_in,check_out,room_id, b_res_id,block_discount, guest = nil) - #how do I get the discounted_rate? must incorpo + #how do I incorporate a block id? @discounted_rate = block_discount - @block_id = block_id - @type= :block + @block_id = nil + @type= :block end #end initialize def cost diff --git a/lib/Booking.rb b/lib/Booking.rb index 8e6a7ad8c..74b745305 100644 --- a/lib/Booking.rb +++ b/lib/Booking.rb @@ -19,8 +19,8 @@ class BookingProgram #NUM_OTHER_ROOMS = 0 def initialize # do we want to initialize with hotel name? - @all_rooms = Hotel::Room.all # returns an array or hash of Room objects - # @all_rooms2 = Hotel::BookingProgram.setup_rooms + # @all_rooms = Hotel::Room.all # returns an array or hash of Room objects + @all_rooms = Hotel::BookingProgram.setup_rooms @all_reservations = [] @all_blocks = [] @@ -38,6 +38,29 @@ def available_rooms(check_in,check_out, block_id = nil) #if block_id end + def find_room_by_id(room_id) + @all_rooms.each {|room| return room if room.id == room_id} + + raise ArgumentError.new "Sorry, we don't have a room matching that ID number." + end + + def make_block(check_in,check_out,room_ids,discounted_rate) + + raise ArgumentError.new("Number of rooms in a block must be 5 or under") if room_ids.count > 5 + + block_id = @all_blocks.count + 1 + + block = Hotel::Block.new(check_in,check_out,room_ids,discounted_rate,block_id) + block.room_ids.each do |room_id| + room = find_room_by_id(room_id) + room.block_room(check_in,check_out,block_id) + end + + @all_blocks << block + + end + + ###should this be a Room method def make_reservation(check_in,check_out,room_id, block_id = nil, guest_id=nil) @@ -46,49 +69,39 @@ def make_reservation(check_in,check_out,room_id, block_id = nil, guest_id=nil) if block_id #TODO: think about whether or not to have a separate block reservation id logic and whether or not to store block reservations in the same place as all reservations AND store them separately, or store them in one place (either all reservations or Block reservations) + all_block_ids = @all_blocks.map {|block| block.id} + raise ArgumentError.new("This block doesn't exist") if !(all_block_ids.include?(block_id)) + block= find_block_by_id(block_id) - raise ArgumentError.new("This block doesn't exist") if !(find_block_by_id(block_id)) + # binding.pry block_discount = block.discounted_rate - block_room = Hotel::Room.find_by_id(room_id)#must be included in the block - raise ArgumentError.new("This room is not in the block") if !(block.rooms.include?(block_room)) + + raise ArgumentError.new("This room is not in the block") if !(block.room_ids.include?(room_id)) #TODO: IRON OUT and TEST block reservation constraints: check in and check out MUST be that of the BLOCK check_in/Check_out dates block_check_in = block.check_in.to_s block_check_out= block.check_out.to_s #TODO: Think about if we want to make a block reservation id a +1 count of all reservations, or have separate ids for blocks - reservation = Hotel::BlockReservation.new(block_check_in,block_check_out,room_id, reservation_id, block_discount, block_id) + reservation = Hotel::BlockReservation.new(block_check_in,block_check_out,room_id, reservation_id, block_discount) + + reservation.block_id = block_id else reservation = Hotel::Reservation.new(check_in,check_out,room_id, reservation_id,block_id) end #TODO: How to incorporate reserve_room logic for Block Reservations - reservation.room.reserve_room(check_in,check_out,reservation.id, guest_id) if reservation.type == :standard + room = find_room_by_id(room_id) + room.reserve_room(check_in,check_out,reservation.id, guest_id) if reservation.type == :standard - reservation.room.reserve_block_room(check_in,check_out,reservation.id, block_id, guest_id=nil) if reservation.type == :block + room.reserve_block_room(check_in,check_out,reservation.id, block_id, guest_id=nil) if reservation.type == :block @all_reservations << reservation end - def make_block(check_in,check_out,room_ids,discounted_rate) - - raise ArgumentError.new("Number of rooms in a block must be 5 or under") if room_ids.count > 5 - - block_id = @all_blocks.count + 1 - - block = Hotel::Block.new(check_in,check_out,room_ids,discounted_rate,block_id) - - block.rooms.each do |room| - room.block_room(check_in,check_out,block_id) - end - - @all_blocks << block - - end - # def make_block_res(check_in,check_out,room_id, block_id, type = :block, guest_id=nil) # room= Hotel::Room.find_by_id(room_id) # block = find_block_by_id(block_id) @@ -110,7 +123,14 @@ def make_block(check_in,check_out,room_ids,discounted_rate) def find_res_by_date(date_str) date_object= Date.parse(date_str) reserved_on_date = [] - @all_reservations.each {|reservation| reserved_on_date << reservation if reservation.room.all_dates.include?(date_object)} + @all_reservations.each do |reservation| + room= find_room_by_id(reservation.room_id) + + reserved_on_date << reservation if room.all_dates.include?(date_object) + end + + + # {|reservation| reserved_on_date << reservation if reservation.room.all_dates.include?(date_object)} return reserved_on_date @@ -129,18 +149,20 @@ def find_block_by_id(block_id) return false end - # def self.setup_rooms - # i = 1 - # standard_rooms = [] - # - # until standard_rooms.count == NUM_STANDARD_ROOMS - # room = Hotel::Room.new(i) - # standard_rooms << room - # i += 1 - # end - # - # return standard_rooms - # end + def self.setup_rooms + i = 1 + standard_rooms = [] + + until standard_rooms.count == NUM_STANDARD_ROOMS + room = Hotel::Room.new(i) + standard_rooms << room + i += 1 + end + + return standard_rooms + + #can modify to set up for different types of rooms + end diff --git a/lib/Reservation.rb b/lib/Reservation.rb index d2e608a7c..06eadd1a0 100644 --- a/lib/Reservation.rb +++ b/lib/Reservation.rb @@ -3,16 +3,14 @@ module Hotel class Reservation - attr_accessor :id, :guest, :check_in, :check_out, :room + attr_accessor :id, :guest, :check_in, :check_out, :room_id attr_reader :all_reservations, :type - @@all_reservations = [] - def initialize(check_in,check_out,room_id, res_id, discounted_rate = nil, guest = nil) @id = res_id @check_in = Date.parse(check_in) #ruby Date object @check_out = Date.parse(check_out) #ruby Date object - @room= Hotel::Room.find_by_id(room_id) # later, this will be a room object assigned via namespacing method Hotel::Room.find_by(room_id) + @room_id= room_id # later, this will be a room object assigned via namespacing method Hotel::Room.find_by(room_id) @guest = guest #Optional- create guest object @discounted_rate = discounted_rate @type= :standard @@ -26,8 +24,10 @@ def self.all #returns array end + ###TODO: CHANGE IMPLEMENTATION OF ROOM COST BELOW + def cost - num_nights_charged * @room.nightly_rate + num_nights_charged * 200 end def num_nights_charged diff --git a/lib/Room.rb b/lib/Room.rb index 60fa081d7..755569638 100644 --- a/lib/Room.rb +++ b/lib/Room.rb @@ -2,6 +2,7 @@ require 'date' require_relative 'Reservation' require_relative 'BlockReservation' +require_relative 'Booking' module Hotel @@ -48,13 +49,22 @@ def reserve_room(check_in_str,check_out_str,reservation_id, guest_id=nil) end def reserve_block_room(check_in_str,check_out_str,reservation_id, block_id, guest_id=nil) + + #TODO: maybe reserve block room should only take in a Block id, since the check-in and check-out dates will be whatever the dates of the block are + + #def reserve_block_room(block_id, reservation_id) + # block = Hotel::BookingProgram.all_blocks.find_block_by_id(block_id) + # + # check_in = block.check_in.to_s + # check_out = block.check_out.to_s + check_in = Date.parse(check_in_str) check_out = Date.parse(check_out_str) check_valid_dates(check_in,check_out) (check_in...check_out).each do |date| - raise ArgumentError.new("this room has already been reserved for these dates in this block") if @block_id_and_res_dates[block_id].include? + raise ArgumentError.new("this room has already been reserved for these dates in this block") if @block_id_and_res_dates[block_id].include?(date) end (check_in...check_out).each do |date| diff --git a/specs/BlockReservation_spec.rb b/specs/BlockReservation_spec.rb index 9ca5fc7fd..14f2835b1 100644 --- a/specs/BlockReservation_spec.rb +++ b/specs/BlockReservation_spec.rb @@ -11,18 +11,15 @@ b_res_id = 14 discounted_rate = 5 block_id = 42 + new_block_res = Hotel::BlockReservation.new(check_in_str, check_out_str,room_id,b_res_id,discounted_rate, block_id) new_block_res.must_be_instance_of Hotel::BlockReservation - # new_block.rooms.must_be_instance_of Array - # new_block.rooms.each do |room| - # room.must_be_instance_of Hotel::Room - # end end end - xdescribe "num_nights_charged" do + describe "num_nights_charged" do it "correctly inherits the num_nights_charged method from the Hotel::Reservation class" do blockres1 = Hotel::BlockReservation.new("2018-02-14", "2018-02-16",3,14,5) @@ -31,7 +28,7 @@ end end - xdescribe "cost" do + describe "cost" do it "calculates cost with a discounted rate" do discounted_rate = 5 blockres1 = Hotel::BlockReservation.new("2018-02-14", "2018-02-16",14,42,discounted_rate) diff --git a/specs/Block_spec.rb b/specs/Block_spec.rb index 7761f000e..eb653f73c 100644 --- a/specs/Block_spec.rb +++ b/specs/Block_spec.rb @@ -11,10 +11,10 @@ new_block = Hotel::Block.new(check_in_str, check_out_str,room_ids,discounted_rate,block_id) new_block.must_be_instance_of Hotel::Block - # new_block.rooms.must_be_instance_of Array - # new_block.rooms.each do |room| - # room.must_be_instance_of Hotel::Room - # end + new_block.room_ids.must_be_instance_of Array + new_block.room_ids.each do |room| + room.must_be_instance_of Integer + end end end diff --git a/specs/Booking_spec.rb b/specs/Booking_spec.rb index aa946628a..f7fd45165 100644 --- a/specs/Booking_spec.rb +++ b/specs/Booking_spec.rb @@ -48,11 +48,41 @@ new_reservation.must_be_instance_of Hotel::Reservation new_reservation.id.must_equal 1 + + new_res_room = new_hotel.find_room_by_id(new_reservation.room_id) (Date.parse("2018-03-14")...Date.parse("2018-03-16")).to_a.each do |date| - new_reservation.room.all_dates.must_include date + new_res_room.all_dates.must_include date end end + + it "makes a BlockReservation object if given a block_id" do + new_hotel = Hotel::BookingProgram.new + room_id = 3 + non_exist_block_id = 2 + block_id = 1 + + check_in = "2018-11-10" + check_out = "2018-11-12" + + proc {new_hotel.make_reservation(check_in, check_out, room_id, block_id)}.must_raise ArgumentError + + new_hotel.make_block(check_in,check_out,[1,3,5],10) + + new_hotel.all_blocks.count.must_equal 1 + + proc {new_hotel.make_reservation(check_in,check_out,room_id,non_exist_block_id)}.must_raise ArgumentError + + # binding.pry + + new_hotel.make_reservation(check_in,check_out,room_id,block_id) + + + + + + end + end describe "make block" do @@ -69,7 +99,8 @@ new_block.must_be_instance_of Hotel::Block new_block.id.must_equal 1 - new_block.rooms.each do |room| + new_block.room_ids.each do |room_id| + room = new_hotel.find_room_by_id(room_id) (Date.parse("2018-03-14")...Date.parse("2018-03-16")).to_a.each do |date| room.all_dates.must_include date #fix this logic later end @@ -132,4 +163,63 @@ end #end available_rooms + + + describe "self.find_block_by_id" do + it "can find the first and last block" do + new_hotel = Hotel::BookingProgram.new + # binding.pry + # new_hotel.find_block_by_id(1).must_equal false + + new_hotel.make_block("2018-06-13", "2018-06-15", [3,4,5], 15) + + first_block = new_hotel.all_blocks[0] + first_block.must_be_instance_of Hotel::Block + first_block.id.must_equal 1 + + found_block = new_hotel.find_block_by_id(1) + + found_block.must_equal first_block + + end + + end + + xdescribe "self.setup_rooms" do + it "returns an array of all room objects, with the accurate number of rooms" do + test_all_rooms = Hotel::BookingProgram.setup_rooms + + test_all_rooms.must_be_instance_of Array + + test_all_rooms.each do |room| + room.must_be_instance_of Hotel::Room + room.nightly_rate.must_equal 200 + end + + test_all_rooms.count.must_equal 20 + + end + + end #end self.setup_rooms + + # xdescribe "find_room_by_id" do + # it "can find the first and last room" do + # new_hotel = Hotel::BookingProgram.new + # + # first_room_id =1 + # last_room_id = 20 + # + # + # first_room = new_hotel.find_room_by_id(first_room_id) + # last_room = new_hotel.find_room_by_id(last_room_id) + # + # first_room.must_be_instance_of Hotel::Room + # first_room.id.must_equal 1 + # + # last_room.must_be_instance_of Hotel::Room + # last_room.id.must_equal 20 + # end + # end end + +binding.pry diff --git a/specs/Reservation_spec.rb b/specs/Reservation_spec.rb index 7abd2864a..e72ed9ea6 100644 --- a/specs/Reservation_spec.rb +++ b/specs/Reservation_spec.rb @@ -22,7 +22,7 @@ read_res.check_in.day.must_equal 1 read_res.check_out.day.must_equal 3 read_res.id.must_equal 100 - read_res.room.id.must_equal 5 + read_res.room_id.must_equal 5 end end #end initialize tests diff --git a/specs/Room_spec.rb b/specs/Room_spec.rb index 99e709e40..478cfeff5 100644 --- a/specs/Room_spec.rb +++ b/specs/Room_spec.rb @@ -153,5 +153,68 @@ end end + xdescribe "reserve_block_room" do + it "can reserve a room if given the check-in/out date, reservation id, and guest id" do + hotel = Hotel::BookingProgram.new + + rooms_in_block = [1,3] + + block_room_wanted = 3 + + check_in_str = "2018-08-09" + check_out_str = "2018-08-12" + discounted_rate = 10 + + hotel.make_block(check_in_str, check_out_str, rooms_in_block,discounted_rate) + + block1 = hotel.all_blocks[0] + + hotel.all_blocks.count.must_equal 1 + block1.must_be_instance_of Hotel::Block + block1.id.must_equal 1 + + room = Hotel::Room.find_by_id(block_room_wanted) + + #check for when trying to make a block reservation for a room that is not in the block e.g.proc{room.reserve_block_room(check_in_str, check_out_str, 1, 20)}.must_raise ArgumentError + + room.reserve_block_room(check_in_str, check_out_str, 99, block1.id) + + (Date.parse(check_in_str)...Date.parse(check_out_str)).each do |date| + room.all_dates.must_include date + end + + (Date.parse(check_in_str)...Date.parse(check_out_str)).each do |date| + room.block_id_and_res_dates[block1.id].must_include date + end + + end + + xit "Raises an error when we try to book a room with a check-in or check-out date earlier than today" do + room = Hotel::Room.new(123) + check_in_str = "2016-08-09" + check_out_str = "2016-08-12" + + proc { room.reserve_block_room(check_in_str, check_out_str, 1, 13)}.must_raise ArgumentError + end + + xit "raises an error if the check-in or check-out date is invalid" do + room = Hotel::Room.new(123) + check_in_str = "February 30, 2018" + check_out_str = "February 31, 2018" + + proc { room.reserve_block_room(check_in_str, check_out_str, 1, 13)}.must_raise ArgumentError + + end + + xit "raises an error if the check-out dates is earlier than the check-in date" do + room = Hotel::Room.new(123) + check_in_str = "March 3, 2018" + check_out_str = "February 20, 2018" + + proc { room.reserve_block_room(check_in_str, check_out_str, 1, 13)}.must_raise ArgumentError + end + + end #end reserve_block_room + end #end Hotel::Room class tests From 7aa52b84546db537d11f8fa1c60178d38d1ee33c Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Fri, 8 Sep 2017 15:18:17 -0700 Subject: [PATCH 21/27] Renamed the Module to be the HotelBooking, and the class to Hotel to be more intuitive with design logic - HotelBooking module has a Hotel, which has Rooms, Reservations, Blocks, and Block Reservations, which in turn have dates --- lib/Block.rb | 4 +- lib/BlockReservation.rb | 8 ++-- lib/Booking.rb | 14 +++---- lib/Reservation.rb | 14 +++---- lib/Room.rb | 4 +- specs/BlockReservation_spec.rb | 14 +++---- specs/Block_spec.rb | 6 +-- specs/Booking_spec.rb | 70 +++++++++++++++++----------------- specs/Reservation_spec.rb | 20 +++++----- specs/Room_spec.rb | 42 ++++++++++---------- 10 files changed, 97 insertions(+), 99 deletions(-) diff --git a/lib/Block.rb b/lib/Block.rb index 8146da5b2..caebd50ba 100644 --- a/lib/Block.rb +++ b/lib/Block.rb @@ -1,6 +1,6 @@ require 'pry' -module Hotel +module HotelBooking class Block attr_accessor :id, :guest, :check_in, :check_out, :room_ids attr_reader :discounted_rate @@ -11,7 +11,7 @@ def initialize(check_in,check_out,room_ids,discounted_rate,block_id) @room_ids = room_ids @discounted_rate = discounted_rate # room_ids.each do |id| - # room = Hotel::BookingProgram.find_room_by_id(id) + # room = HotelBooking::Hotel.find_room_by_id(id) # # room.reserve_room(check_in,check_out,@id) # @rooms << room # end diff --git a/lib/BlockReservation.rb b/lib/BlockReservation.rb index fb37b8996..bd5c294f1 100644 --- a/lib/BlockReservation.rb +++ b/lib/BlockReservation.rb @@ -3,21 +3,21 @@ require_relative 'Reservation' require_relative 'Booking' -module Hotel - class BlockReservation < Hotel::Reservation +module HotelBooking + class BlockReservation < HotelBooking::Reservation attr_accessor :id, :guest, :check_in, :check_out, :room, :block_id attr_reader :all_reservations, :type def initialize(check_in,check_out,room_id, b_res_id, block_discount,guest = nil) super(check_in,check_out,room_id, b_res_id,block_discount, guest = nil) #how do I incorporate a block id? - @discounted_rate = block_discount + @rate = block_discount @block_id = nil @type= :block end #end initialize def cost - num_nights_charged * @discounted_rate + num_nights_charged * @rate end end end diff --git a/lib/Booking.rb b/lib/Booking.rb index 74b745305..728dda803 100644 --- a/lib/Booking.rb +++ b/lib/Booking.rb @@ -10,17 +10,17 @@ ## THINK THROUGH: Does a Room create a Reservation based on availability vs. does a Reservation, once created, reserve a room? -module Hotel +module HotelBooking # NUMBER_OF_ROOMS = 20 ### might not want to use constant, especially if we have subclasses of rooms (by type), and each room subclass might have a different number. may best be a constant defined by class/subclass - class BookingProgram + class Hotel attr_reader :all_rooms, :all_reservations, :all_blocks NUM_STANDARD_ROOMS = 20 #NUM_OTHER_ROOMS = 0 def initialize # do we want to initialize with hotel name? # @all_rooms = Hotel::Room.all # returns an array or hash of Room objects - @all_rooms = Hotel::BookingProgram.setup_rooms + @all_rooms = HotelBooking::Hotel.setup_rooms @all_reservations = [] @all_blocks = [] @@ -50,7 +50,7 @@ def make_block(check_in,check_out,room_ids,discounted_rate) block_id = @all_blocks.count + 1 - block = Hotel::Block.new(check_in,check_out,room_ids,discounted_rate,block_id) + block = HotelBooking::Block.new(check_in,check_out,room_ids,discounted_rate,block_id) block.room_ids.each do |room_id| room = find_room_by_id(room_id) room.block_room(check_in,check_out,block_id) @@ -85,11 +85,11 @@ def make_reservation(check_in,check_out,room_id, block_id = nil, guest_id=nil) block_check_out= block.check_out.to_s #TODO: Think about if we want to make a block reservation id a +1 count of all reservations, or have separate ids for blocks - reservation = Hotel::BlockReservation.new(block_check_in,block_check_out,room_id, reservation_id, block_discount) + reservation = HotelBooking::BlockReservation.new(block_check_in,block_check_out,room_id, reservation_id, block_discount) reservation.block_id = block_id else - reservation = Hotel::Reservation.new(check_in,check_out,room_id, reservation_id,block_id) + reservation = HotelBooking::Reservation.new(check_in,check_out,room_id, reservation_id,block_id) end #TODO: How to incorporate reserve_room logic for Block Reservations @@ -154,7 +154,7 @@ def self.setup_rooms standard_rooms = [] until standard_rooms.count == NUM_STANDARD_ROOMS - room = Hotel::Room.new(i) + room = HotelBooking::Room.new(i) standard_rooms << room i += 1 end diff --git a/lib/Reservation.rb b/lib/Reservation.rb index 06eadd1a0..389cca4b4 100644 --- a/lib/Reservation.rb +++ b/lib/Reservation.rb @@ -1,18 +1,18 @@ require 'pry' require 'date' -module Hotel +module HotelBooking class Reservation attr_accessor :id, :guest, :check_in, :check_out, :room_id - attr_reader :all_reservations, :type + attr_reader :all_reservations, :type, :rate - def initialize(check_in,check_out,room_id, res_id, discounted_rate = nil, guest = nil) + def initialize(check_in,check_out,room_id, res_id, rate = 200, guest = nil) @id = res_id @check_in = Date.parse(check_in) #ruby Date object @check_out = Date.parse(check_out) #ruby Date object - @room_id= room_id # later, this will be a room object assigned via namespacing method Hotel::Room.find_by(room_id) - @guest = guest #Optional- create guest object - @discounted_rate = discounted_rate + @room_id= room_id + @guest = guest + @rate = rate @type= :standard end #end initialize @@ -27,7 +27,7 @@ def self.all #returns array ###TODO: CHANGE IMPLEMENTATION OF ROOM COST BELOW def cost - num_nights_charged * 200 + num_nights_charged * @rate end def num_nights_charged diff --git a/lib/Room.rb b/lib/Room.rb index 755569638..838b504c9 100644 --- a/lib/Room.rb +++ b/lib/Room.rb @@ -4,7 +4,7 @@ require_relative 'BlockReservation' require_relative 'Booking' -module Hotel +module HotelBooking class Room attr_reader :id, :nightly_rate, :type, :reserv_id_and_dates, :all_dates, :block_id_and_dates @@ -98,7 +98,7 @@ def self.all all_rooms = [] until all_rooms.count == @@total_num_rooms - room = Hotel::Room.new(i) + room = HotelBooking::Room.new(i) all_rooms << room i += 1 end diff --git a/specs/BlockReservation_spec.rb b/specs/BlockReservation_spec.rb index 14f2835b1..30697425f 100644 --- a/specs/BlockReservation_spec.rb +++ b/specs/BlockReservation_spec.rb @@ -2,7 +2,7 @@ require 'pry' require_relative 'spec_helper' -describe "Hotel::BlockReservation class" do +describe "HotelBooking::BlockReservation class" do describe "initialize" do it "initalizes" do check_in_str = "2018-10-03" @@ -12,17 +12,17 @@ discounted_rate = 5 block_id = 42 - new_block_res = Hotel::BlockReservation.new(check_in_str, check_out_str,room_id,b_res_id,discounted_rate, block_id) + new_block_res = HotelBooking::BlockReservation.new(check_in_str, check_out_str,room_id,b_res_id,discounted_rate, block_id) - new_block_res.must_be_instance_of Hotel::BlockReservation + new_block_res.must_be_instance_of HotelBooking::BlockReservation end end describe "num_nights_charged" do - it "correctly inherits the num_nights_charged method from the Hotel::Reservation class" do - blockres1 = Hotel::BlockReservation.new("2018-02-14", "2018-02-16",3,14,5) + it "correctly inherits the num_nights_charged method from the HotelBooking::Reservation class" do + blockres1 = HotelBooking::BlockReservation.new("2018-02-14", "2018-02-16",3,14,5) blockres1.num_nights_charged.must_equal 2 end @@ -31,10 +31,10 @@ describe "cost" do it "calculates cost with a discounted rate" do discounted_rate = 5 - blockres1 = Hotel::BlockReservation.new("2018-02-14", "2018-02-16",14,42,discounted_rate) + blockres1 = HotelBooking::BlockReservation.new("2018-02-14", "2018-02-16",14,42,discounted_rate) blockres1.cost.must_equal 10 - blockres2 = Hotel::BlockReservation.new("2018-12-01", "2018-12-02",1,5,discounted_rate) + blockres2 = HotelBooking::BlockReservation.new("2018-12-01", "2018-12-02",1,5,discounted_rate) blockres2.cost.must_equal 5 end diff --git a/specs/Block_spec.rb b/specs/Block_spec.rb index eb653f73c..f39dd2fdf 100644 --- a/specs/Block_spec.rb +++ b/specs/Block_spec.rb @@ -1,6 +1,6 @@ require_relative 'spec_helper' -describe "Hotel::Block class " do +describe "HotelBooking::Block class " do describe "initialize" do it "initalizes" do check_in_str = "2018-10-03" @@ -8,9 +8,9 @@ room_ids = [1,2,3] block_id = "Amy's Party" discounted_rate = 5 - new_block = Hotel::Block.new(check_in_str, check_out_str,room_ids,discounted_rate,block_id) + new_block = HotelBooking::Block.new(check_in_str, check_out_str,room_ids,discounted_rate,block_id) - new_block.must_be_instance_of Hotel::Block + new_block.must_be_instance_of HotelBooking::Block new_block.room_ids.must_be_instance_of Array new_block.room_ids.each do |room| room.must_be_instance_of Integer diff --git a/specs/Booking_spec.rb b/specs/Booking_spec.rb index f7fd45165..00035e1e9 100644 --- a/specs/Booking_spec.rb +++ b/specs/Booking_spec.rb @@ -1,13 +1,13 @@ require_relative 'spec_helper' -describe "BookingProgram" do +describe "Hotel" do describe "Initialize" do it "initializes with 20 rooms, numbered 1 through 20 and I can can access the list of all rooms " do - new_hotel = Hotel::BookingProgram.new + new_hotel = HotelBooking::Hotel.new new_hotel.all_rooms.must_be_instance_of Array new_hotel.all_rooms.each do |room| - room.must_be_instance_of Hotel::Room + room.must_be_instance_of HotelBooking::Room end @@ -17,7 +17,7 @@ describe "find_res_by_date" do it "Returns an array of Reservation objects" do - new_hotel = Hotel::BookingProgram.new + new_hotel = HotelBooking::Hotel.new new_hotel.make_reservation("2018-03-14", "2018-04-16", 3) @@ -39,14 +39,14 @@ describe "make reservation" do it "reserves a Room and makes a Reservation object " do - new_hotel = Hotel::BookingProgram.new + new_hotel = HotelBooking::Hotel.new new_hotel.make_reservation("2018-03-14", "2018-03-16", 3) new_reservation = new_hotel.all_reservations[0] - new_reservation.must_be_instance_of Hotel::Reservation + new_reservation.must_be_instance_of HotelBooking::Reservation new_reservation.id.must_equal 1 new_res_room = new_hotel.find_room_by_id(new_reservation.room_id) @@ -57,7 +57,7 @@ end it "makes a BlockReservation object if given a block_id" do - new_hotel = Hotel::BookingProgram.new + new_hotel = HotelBooking::Hotel.new room_id = 3 non_exist_block_id = 2 block_id = 1 @@ -89,14 +89,14 @@ it "creates a Block and reserves a room" do #note, need to fix: it shouldn't reserve room officially, but should be "Blocked off" test for this when the functionality is made - new_hotel = Hotel::BookingProgram.new + new_hotel = HotelBooking::Hotel.new new_hotel.make_block("2018-03-14", "2018-03-16",[18,19,20], 2) new_block = new_hotel.all_blocks[0] - new_block.must_be_instance_of Hotel::Block + new_block.must_be_instance_of HotelBooking::Block new_block.id.must_equal 1 new_block.room_ids.each do |room_id| @@ -113,7 +113,7 @@ describe "available_rooms" do before do - @new_hotel = Hotel::BookingProgram.new + @new_hotel = HotelBooking::Hotel.new @check_in = "June 1, 2018" @check_out = "June 30, 2018" @june_rooms = @new_hotel.available_rooms(@check_in, @check_out) @@ -124,7 +124,7 @@ @june_rooms.must_be_instance_of Array @june_rooms.count.must_equal 20 @june_rooms.each do |room| - room.must_be_instance_of Hotel::Room + room.must_be_instance_of HotelBooking::Room end end @@ -167,14 +167,14 @@ describe "self.find_block_by_id" do it "can find the first and last block" do - new_hotel = Hotel::BookingProgram.new + new_hotel = HotelBooking::Hotel.new # binding.pry # new_hotel.find_block_by_id(1).must_equal false new_hotel.make_block("2018-06-13", "2018-06-15", [3,4,5], 15) first_block = new_hotel.all_blocks[0] - first_block.must_be_instance_of Hotel::Block + first_block.must_be_instance_of HotelBooking::Block first_block.id.must_equal 1 found_block = new_hotel.find_block_by_id(1) @@ -185,14 +185,14 @@ end - xdescribe "self.setup_rooms" do + describe "self.setup_rooms" do it "returns an array of all room objects, with the accurate number of rooms" do - test_all_rooms = Hotel::BookingProgram.setup_rooms + test_all_rooms = HotelBooking::Hotel.setup_rooms test_all_rooms.must_be_instance_of Array test_all_rooms.each do |room| - room.must_be_instance_of Hotel::Room + room.must_be_instance_of HotelBooking::Room room.nightly_rate.must_equal 200 end @@ -202,24 +202,22 @@ end #end self.setup_rooms - # xdescribe "find_room_by_id" do - # it "can find the first and last room" do - # new_hotel = Hotel::BookingProgram.new - # - # first_room_id =1 - # last_room_id = 20 - # - # - # first_room = new_hotel.find_room_by_id(first_room_id) - # last_room = new_hotel.find_room_by_id(last_room_id) - # - # first_room.must_be_instance_of Hotel::Room - # first_room.id.must_equal 1 - # - # last_room.must_be_instance_of Hotel::Room - # last_room.id.must_equal 20 - # end - # end -end + describe "find_room_by_id" do + it "can find the first and last room" do + new_hotel = HotelBooking::Hotel.new + + first_room_id =1 + last_room_id = 20 + + + first_room = new_hotel.find_room_by_id(first_room_id) + last_room = new_hotel.find_room_by_id(last_room_id) -binding.pry + first_room.must_be_instance_of HotelBooking::Room + first_room.id.must_equal 1 + + last_room.must_be_instance_of HotelBooking::Room + last_room.id.must_equal 20 + end + end +end diff --git a/specs/Reservation_spec.rb b/specs/Reservation_spec.rb index e72ed9ea6..2baa2fa3b 100644 --- a/specs/Reservation_spec.rb +++ b/specs/Reservation_spec.rb @@ -1,20 +1,20 @@ require_relative 'spec_helper' -describe "Hotel::Reservation class" do +describe "HotelBooking::Reservation class" do describe "initialize" do it "requires five arguments, an id, a guest, a check-in date, a check-out date, and a room" do - proc {Hotel::Reservation.new}.must_raise ArgumentError - proc {Hotel::Reservation.new("Jim Bob", "2018-07-01",5)}.must_raise ArgumentError + proc {HotelBooking::Reservation.new}.must_raise ArgumentError + proc {HotelBooking::Reservation.new("Jim Bob", "2018-07-01",5)}.must_raise ArgumentError - new_res = Hotel::Reservation.new("July 1", "2018-07-03", 5, 14) + new_res = HotelBooking::Reservation.new("July 1", "2018-07-03", 5, 14) - new_res.must_be_instance_of Hotel::Reservation + new_res.must_be_instance_of HotelBooking::Reservation end it "creates a Reservation instance that allows us to read the id, guest, check-in date, check-out date, and room " do - read_res = Hotel::Reservation.new("2018-07-01", "2018-07-03", 5,100) + read_res = HotelBooking::Reservation.new("2018-07-01", "2018-07-03", 5,100) - read_res.must_be_instance_of Hotel::Reservation + read_res.must_be_instance_of HotelBooking::Reservation [read_res.check_in, read_res.check_out].each do |date| date.month.must_equal 7 end @@ -29,7 +29,7 @@ describe "self.all" do it "initializes with zero reservations" do - new_hotel_reservations = Hotel::Reservation.all + new_hotel_reservations = HotelBooking::Reservation.all new_hotel_reservations.must_be_instance_of Array new_hotel_reservations.count.must_equal 0 @@ -41,11 +41,11 @@ describe "Cost" do it "Returns an integer value that is the total cost of the reservation" do - reservation = Hotel::Reservation.new("2018-02-14", "2018-02-16",5,1) + reservation = HotelBooking::Reservation.new("2018-02-14", "2018-02-16",5,1) reservation.cost.must_equal 400 - res2 = Hotel::Reservation.new("2018-12-01", "2018-12-02", 17,3) + res2 = HotelBooking::Reservation.new("2018-12-01", "2018-12-02", 17,3) res2.cost.must_equal 200 end diff --git a/specs/Room_spec.rb b/specs/Room_spec.rb index 478cfeff5..c9b1ffac0 100644 --- a/specs/Room_spec.rb +++ b/specs/Room_spec.rb @@ -3,24 +3,24 @@ require_relative 'spec_helper' -describe "Hotel::Room class" do +describe "HotelBooking::Room class" do describe "initialize" do it "requires one argument, number" do - proc {Hotel::Room.new}.must_raise ArgumentError + proc {HotelBooking::Room.new}.must_raise ArgumentError - new_room = Hotel::Room.new(1) - new_room.must_be_instance_of Hotel::Room + new_room = HotelBooking::Room.new(1) + new_room.must_be_instance_of HotelBooking::Room end it "creates a new Room object with the correct id, and initialized with the correct default values for status and nightly_rate" do - new_room = Hotel::Room.new(1) + new_room = HotelBooking::Room.new(1) new_room.id.must_equal 1 new_room.nightly_rate.must_equal 200 end it "can take an optional argument nightly_rate if we want to give it a different nightly_rate" do - vip_room = Hotel::Room.new(100, 350) + vip_room = HotelBooking::Room.new(100, 350) vip_room.id.must_equal 100 vip_room.nightly_rate.must_equal 350 @@ -30,7 +30,7 @@ describe "reserve_room" do it "can reserve a room if given the check-in/out date, reservation id, and guest id" do - room = Hotel::Room.new(666) + room = HotelBooking::Room.new(666) check_in_str = "2018-08-09" check_out_str = "2018-08-12" @@ -52,7 +52,7 @@ end it "Raises an error when we try to book a room with a check-in or check-out date earlier than today" do - room = Hotel::Room.new(123) + room = HotelBooking::Room.new(123) check_in_str = "2016-08-09" check_out_str = "2016-08-12" @@ -60,7 +60,7 @@ end it "raises an error if the check-in or check-out date is invalid" do - room = Hotel::Room.new(123) + room = HotelBooking::Room.new(123) check_in_str = "February 30, 2018" check_out_str = "February 31, 2018" @@ -69,7 +69,7 @@ end it "raises an error if the check-out dates is earlier than the check-in date" do - room = Hotel::Room.new(123) + room = HotelBooking::Room.new(123) check_in_str = "March 3, 2018" check_out_str = "February 20, 2018" @@ -80,12 +80,12 @@ describe "self.all" do it "returns an array of all room objects, with the accurate number of rooms" do - test_all_rooms = Hotel::Room.all + test_all_rooms = HotelBooking::Room.all test_all_rooms.must_be_instance_of Array test_all_rooms.each do |room| - room.must_be_instance_of Hotel::Room + room.must_be_instance_of HotelBooking::Room room.nightly_rate.must_equal 200 end @@ -99,7 +99,7 @@ describe "available_all_days?" do it "returns the correct Boolean value" do - room1 = Hotel::Room.all[0] + room1 = HotelBooking::Room.all[0] check_in = "2018-03-14" check_out = "2018-03-18" @@ -130,7 +130,7 @@ describe "block room" do it "can block a room if given the check-in/out date and block id so that it is unavailable to reserve via regular reservations" do - room = Hotel::Room.new(666) + room = HotelBooking::Room.new(666) check_in_str = "2018-08-09" check_out_str = "2018-08-12" block_id = 3 @@ -155,7 +155,7 @@ xdescribe "reserve_block_room" do it "can reserve a room if given the check-in/out date, reservation id, and guest id" do - hotel = Hotel::BookingProgram.new + hotel = HotelBooking::BookingProgram.new rooms_in_block = [1,3] @@ -170,10 +170,10 @@ block1 = hotel.all_blocks[0] hotel.all_blocks.count.must_equal 1 - block1.must_be_instance_of Hotel::Block + block1.must_be_instance_of HotelBooking::Block block1.id.must_equal 1 - room = Hotel::Room.find_by_id(block_room_wanted) + room = HotelBooking::Room.find_by_id(block_room_wanted) #check for when trying to make a block reservation for a room that is not in the block e.g.proc{room.reserve_block_room(check_in_str, check_out_str, 1, 20)}.must_raise ArgumentError @@ -190,7 +190,7 @@ end xit "Raises an error when we try to book a room with a check-in or check-out date earlier than today" do - room = Hotel::Room.new(123) + room = HotelBooking::Room.new(123) check_in_str = "2016-08-09" check_out_str = "2016-08-12" @@ -198,7 +198,7 @@ end xit "raises an error if the check-in or check-out date is invalid" do - room = Hotel::Room.new(123) + room = HotelBooking::Room.new(123) check_in_str = "February 30, 2018" check_out_str = "February 31, 2018" @@ -207,7 +207,7 @@ end xit "raises an error if the check-out dates is earlier than the check-in date" do - room = Hotel::Room.new(123) + room = HotelBooking::Room.new(123) check_in_str = "March 3, 2018" check_out_str = "February 20, 2018" @@ -217,4 +217,4 @@ end #end reserve_block_room -end #end Hotel::Room class tests +end #end HotelBooking::Room class tests From 35e687faa3e1082a5c4a08971404745216746084 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Sat, 9 Sep 2017 11:00:35 -0700 Subject: [PATCH 22/27] All waves passing, basic tests passing. Need to fix logic for Room's all_dates variable and refactor/refine everything. Frurther testing needed --- lib/Block.rb | 1 - lib/BlockReservation.rb | 4 +-- lib/Booking.rb | 25 +++++++++++++-- lib/Reservation.rb | 10 ------ lib/Room.rb | 9 ++++-- specs/Block_spec.rb | 2 ++ specs/Booking_spec.rb | 67 +++++++++++++++++++++++++++++++-------- specs/Reservation_spec.rb | 12 ------- 8 files changed, 87 insertions(+), 43 deletions(-) diff --git a/lib/Block.rb b/lib/Block.rb index caebd50ba..36d7f43ca 100644 --- a/lib/Block.rb +++ b/lib/Block.rb @@ -17,7 +17,6 @@ def initialize(check_in,check_out,room_ids,discounted_rate,block_id) # end @id = block_id - @all_block_reservations = [] end end diff --git a/lib/BlockReservation.rb b/lib/BlockReservation.rb index bd5c294f1..c6d430e9d 100644 --- a/lib/BlockReservation.rb +++ b/lib/BlockReservation.rb @@ -8,7 +8,7 @@ class BlockReservation < HotelBooking::Reservation attr_accessor :id, :guest, :check_in, :check_out, :room, :block_id attr_reader :all_reservations, :type - def initialize(check_in,check_out,room_id, b_res_id, block_discount,guest = nil) + def initialize(check_in,check_out,room_id, b_res_id, block_discount, guest = nil) super(check_in,check_out,room_id, b_res_id,block_discount, guest = nil) #how do I incorporate a block id? @rate = block_discount @@ -22,4 +22,4 @@ def cost end end -#can I additional parameter block_id, and still use super to inherit from Reservation +#can I have additional parameter block_id, and still use super to inherit from Reservation diff --git a/lib/Booking.rb b/lib/Booking.rb index 728dda803..1463bc928 100644 --- a/lib/Booking.rb +++ b/lib/Booking.rb @@ -10,6 +10,15 @@ ## THINK THROUGH: Does a Room create a Reservation based on availability vs. does a Reservation, once created, reserve a room? +###Should check for valid inputs in Hotel, instead of checking everywhere? + + +##### if designating reservations by type, maybe a subclass of BlockReservations is not needed unless the behaviors are very different +#### same with room types + + +###TODO: BlockReservations Have Ids that are strings. Consider: should Reservations Also have IDs that are Strings + module HotelBooking # NUMBER_OF_ROOMS = 20 ### might not want to use constant, especially if we have subclasses of rooms (by type), and each room subclass might have a different number. may best be a constant defined by class/subclass @@ -48,12 +57,19 @@ def make_block(check_in,check_out,room_ids,discounted_rate) raise ArgumentError.new("Number of rooms in a block must be 5 or under") if room_ids.count > 5 - block_id = @all_blocks.count + 1 + available_rooms_ids = available_rooms(check_in,check_out).map {|room| room.id} + room_ids.each do |room_id| + raise ArgumentError.new("The room you've selected for this block is not available for this time period.") if !(available_rooms_ids.include?(room_id)) + end + + block_id = "B" + "#{@all_blocks.count + 1}" block = HotelBooking::Block.new(check_in,check_out,room_ids,discounted_rate,block_id) + block.room_ids.each do |room_id| room = find_room_by_id(room_id) room.block_room(check_in,check_out,block_id) + room.blocks_available << block_id end @all_blocks << block @@ -69,6 +85,8 @@ def make_reservation(check_in,check_out,room_id, block_id = nil, guest_id=nil) if block_id #TODO: think about whether or not to have a separate block reservation id logic and whether or not to store block reservations in the same place as all reservations AND store them separately, or store them in one place (either all reservations or Block reservations) + #TODO: IMPLEMTN THIS block_reservation_id = "B" + "#{reservation_id}", if decided to convert all reservation IDs to strings + all_block_ids = @all_blocks.map {|block| block.id} raise ArgumentError.new("This block doesn't exist") if !(all_block_ids.include?(block_id)) @@ -96,7 +114,10 @@ def make_reservation(check_in,check_out,room_id, block_id = nil, guest_id=nil) room = find_room_by_id(room_id) room.reserve_room(check_in,check_out,reservation.id, guest_id) if reservation.type == :standard - room.reserve_block_room(check_in,check_out,reservation.id, block_id, guest_id=nil) if reservation.type == :block + if reservation.type == :block + room.reserve_block_room(check_in,check_out,reservation.id, block_id, guest_id=nil) + room.blocks_available.delete(block_id) + end @all_reservations << reservation diff --git a/lib/Reservation.rb b/lib/Reservation.rb index 389cca4b4..fb1dddacd 100644 --- a/lib/Reservation.rb +++ b/lib/Reservation.rb @@ -16,16 +16,6 @@ def initialize(check_in,check_out,room_id, res_id, rate = 200, guest = nil) @type= :standard end #end initialize - - def self.all #returns array - all_reservations = [] - - return all_reservations - - end - - ###TODO: CHANGE IMPLEMENTATION OF ROOM COST BELOW - def cost num_nights_charged * @rate end diff --git a/lib/Room.rb b/lib/Room.rb index 838b504c9..633aef62d 100644 --- a/lib/Room.rb +++ b/lib/Room.rb @@ -7,7 +7,7 @@ module HotelBooking class Room - attr_reader :id, :nightly_rate, :type, :reserv_id_and_dates, :all_dates, :block_id_and_dates + attr_reader :id, :nightly_rate, :type, :reserv_id_and_dates, :all_dates, :block_id_and_dates, :blocks_available # :status @@total_num_rooms = 20 @@ -20,6 +20,7 @@ def initialize(id_number, nightly_rate = 200) # holds all reservations, a hash with reservation ids as keys and values as the date range of the reservation ### check-out date should not be included @block_id_and_res_dates = {} @all_dates = [] + @blocks_available = [] #block ids that have not been claimed # @status = :available #not sure if status is needed anymore.maybe a method, available? @@ -63,10 +64,14 @@ def reserve_block_room(check_in_str,check_out_str,reservation_id, block_id, gues check_valid_dates(check_in,check_out) + raise ArgumentError.new("This room is not available for this block reservation") if !(@blocks_available.include?(block_id)) + (check_in...check_out).each do |date| raise ArgumentError.new("this room has already been reserved for these dates in this block") if @block_id_and_res_dates[block_id].include?(date) end + #blocks_available.delete(block_id) + (check_in...check_out).each do |date| @block_id_and_res_dates[block_id]<< date end @@ -118,7 +123,7 @@ def available_all_days?(check_in_str, check_out_str) check_in = Date.parse(check_in_str) check_out = Date.parse(check_out_str) - (check_in...check_out).each do |date| + (check_in..check_out).each do |date| ### double check this logic, inclusive rather than exclusive return false if @all_dates.include?(date) end diff --git a/specs/Block_spec.rb b/specs/Block_spec.rb index f39dd2fdf..03da31baf 100644 --- a/specs/Block_spec.rb +++ b/specs/Block_spec.rb @@ -16,6 +16,8 @@ room.must_be_instance_of Integer end + new_block.id.must_equal block_id + end end end diff --git a/specs/Booking_spec.rb b/specs/Booking_spec.rb index 00035e1e9..4410dcd66 100644 --- a/specs/Booking_spec.rb +++ b/specs/Booking_spec.rb @@ -37,11 +37,13 @@ end end #end find_res_by_date - describe "make reservation" do + describe "make_reservation" do it "reserves a Room and makes a Reservation object " do new_hotel = HotelBooking::Hotel.new + check_in ="2018-03-14" + check_out="2018-03-16" - new_hotel.make_reservation("2018-03-14", "2018-03-16", 3) + new_hotel.make_reservation(check_in, check_out, 3) new_reservation = new_hotel.all_reservations[0] @@ -50,7 +52,7 @@ new_reservation.id.must_equal 1 new_res_room = new_hotel.find_room_by_id(new_reservation.room_id) - (Date.parse("2018-03-14")...Date.parse("2018-03-16")).to_a.each do |date| + (Date.parse(check_in)...Date.parse(check_out)).each do |date| new_res_room.all_dates.must_include date end @@ -59,33 +61,40 @@ it "makes a BlockReservation object if given a block_id" do new_hotel = HotelBooking::Hotel.new room_id = 3 - non_exist_block_id = 2 - block_id = 1 + non_exist_block_id = "B2" + + rooms_in_block = [1,3,5] check_in = "2018-11-10" check_out = "2018-11-12" - proc {new_hotel.make_reservation(check_in, check_out, room_id, block_id)}.must_raise ArgumentError + proc {new_hotel.make_reservation(check_in, check_out, room_id, non_exist_block_id)}.must_raise ArgumentError - new_hotel.make_block(check_in,check_out,[1,3,5],10) + new_hotel.make_block(check_in,check_out,rooms_in_block,10) new_hotel.all_blocks.count.must_equal 1 + new_block = new_hotel.all_blocks[0] + block_id = new_block.id + proc {new_hotel.make_reservation(check_in,check_out,room_id,non_exist_block_id)}.must_raise ArgumentError # binding.pry new_hotel.make_reservation(check_in,check_out,room_id,block_id) + new_block_reservation = new_hotel.all_reservations[-1] + new_block_reservation.block_id.must_equal "B1" + # binding.pry + end - - + it "allows another guest to check-in to a room on the same day another guest checks out" do end end - describe "make block" do + describe "make_block" do it "creates a Block and reserves a room" do #note, need to fix: it shouldn't reserve room officially, but should be "Blocked off" test for this when the functionality is made @@ -97,7 +106,7 @@ new_block.must_be_instance_of HotelBooking::Block - new_block.id.must_equal 1 + new_block.id.must_equal "B1" new_block.room_ids.each do |room_id| room = new_hotel.find_room_by_id(room_id) @@ -105,7 +114,33 @@ room.all_dates.must_include date #fix this logic later end end + end + + it "does not allow you to create a Block if the room is reserved for any of the dates within the range you've proposed" do + new_hotel = HotelBooking::Hotel.new + + check_in= "2018-04-03" + check_out = "2018-04-17" + room_id = 5 + new_hotel.make_reservation(check_in,check_out,room_id) + + room = new_hotel.find_room_by_id(room_id) + + (Date.parse(check_in)...Date.parse(check_out)).to_a.each do |date| + room.all_dates.must_include date + end + + block_start= "2018-04-01" + proc{new_hotel.make_block(block_start,check_in,[1,5],10)}.must_raise ArgumentError + + block_start2 = "2018-04-05" + block_end = "2018-04-08" + + proc{new_hotel.make_block(block_start2,block_end,[1,5],10)}.must_raise ArgumentError + + block_end2 = "2018-05-01" + new_hotel.make_block(check_out,block_end2,[1,5],10) end end @@ -165,19 +200,21 @@ - describe "self.find_block_by_id" do + describe "find_block_by_id" do it "can find the first and last block" do new_hotel = HotelBooking::Hotel.new # binding.pry # new_hotel.find_block_by_id(1).must_equal false + # binding.pry + new_hotel.make_block("2018-06-13", "2018-06-15", [3,4,5], 15) first_block = new_hotel.all_blocks[0] first_block.must_be_instance_of HotelBooking::Block - first_block.id.must_equal 1 + first_block.id.must_equal "B1" - found_block = new_hotel.find_block_by_id(1) + found_block = new_hotel.find_block_by_id("B1") found_block.must_equal first_block @@ -215,9 +252,11 @@ first_room.must_be_instance_of HotelBooking::Room first_room.id.must_equal 1 + first_room.must_equal new_hotel.all_rooms[0] last_room.must_be_instance_of HotelBooking::Room last_room.id.must_equal 20 + last_room.must_equal new_hotel.all_rooms[-1] end end end diff --git a/specs/Reservation_spec.rb b/specs/Reservation_spec.rb index 2baa2fa3b..cb43d0521 100644 --- a/specs/Reservation_spec.rb +++ b/specs/Reservation_spec.rb @@ -27,18 +27,6 @@ end #end initialize tests - describe "self.all" do - it "initializes with zero reservations" do - new_hotel_reservations = HotelBooking::Reservation.all - - new_hotel_reservations.must_be_instance_of Array - new_hotel_reservations.count.must_equal 0 - end - - - end #end self.all - - describe "Cost" do it "Returns an integer value that is the total cost of the reservation" do reservation = HotelBooking::Reservation.new("2018-02-14", "2018-02-16",5,1) From 6e20e8cc3696f64a5c0e4d7766a0a68ec7dcd3c6 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Sat, 9 Sep 2017 16:49:33 -0700 Subject: [PATCH 23/27] Refactored Room - Rooms only keep track of the IDS for reservations and blocks, and one array for all reserved dates. Hotel will hav methods to find reservations and blocks by IDs as needed --- lib/Booking.rb | 27 +++++++++++++++++---------- lib/Room.rb | 35 +++++++++++++---------------------- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/lib/Booking.rb b/lib/Booking.rb index 1463bc928..04fe79629 100644 --- a/lib/Booking.rb +++ b/lib/Booking.rb @@ -69,7 +69,6 @@ def make_block(check_in,check_out,room_ids,discounted_rate) block.room_ids.each do |room_id| room = find_room_by_id(room_id) room.block_room(check_in,check_out,block_id) - room.blocks_available << block_id end @all_blocks << block @@ -81,6 +80,7 @@ def make_block(check_in,check_out,room_ids,discounted_rate) def make_reservation(check_in,check_out,room_id, block_id = nil, guest_id=nil) reservation_id = (@all_reservations.count + 1) #something + room= find_room_by_id(room_id) if block_id #TODO: think about whether or not to have a separate block reservation id logic and whether or not to store block reservations in the same place as all reservations AND store them separately, or store them in one place (either all reservations or Block reservations) @@ -104,21 +104,28 @@ def make_reservation(check_in,check_out,room_id, block_id = nil, guest_id=nil) #TODO: Think about if we want to make a block reservation id a +1 count of all reservations, or have separate ids for blocks reservation = HotelBooking::BlockReservation.new(block_check_in,block_check_out,room_id, reservation_id, block_discount) - reservation.block_id = block_id + + room.reserve_block_room(block_check_in,block_check_out,reservation.id, block_id, guest_id=nil) + else reservation = HotelBooking::Reservation.new(check_in,check_out,room_id, reservation_id,block_id) - end - - #TODO: How to incorporate reserve_room logic for Block Reservations - room = find_room_by_id(room_id) - room.reserve_room(check_in,check_out,reservation.id, guest_id) if reservation.type == :standard - if reservation.type == :block - room.reserve_block_room(check_in,check_out,reservation.id, block_id, guest_id=nil) - room.blocks_available.delete(block_id) + room.reserve_room(check_in,check_out,reservation_id, guest_id) end + # #TODO: How to incorporate reserve_room logic for Block Reservations + # room = find_room_by_id(room_id) + # room.reserve_room(check_in,check_out,reservation.id, guest_id) if reservation.type == :standard + + # if reservation.type == :block + # + # check_in_str,check_out_str,reservation_id, block_id, guest_id=nil) + # + # room.reserve_block_room(check_in,check_out,reservation.id, block_id, guest_id=nil) + # room.blocks_available.delete(block_id) + # end + @all_reservations << reservation end diff --git a/lib/Room.rb b/lib/Room.rb index 633aef62d..e3250a2dd 100644 --- a/lib/Room.rb +++ b/lib/Room.rb @@ -7,7 +7,7 @@ module HotelBooking class Room - attr_reader :id, :nightly_rate, :type, :reserv_id_and_dates, :all_dates, :block_id_and_dates, :blocks_available + attr_reader :id, :nightly_rate, :type, :reserv_ids, :all_dates, :block_ids, :blocks_available # :status @@total_num_rooms = 20 @@ -16,9 +16,9 @@ def initialize(id_number, nightly_rate = 200) @id = id_number @nightly_rate = nightly_rate @type = :standard # is this necessary - @reserv_id_and_dates = {} + @reserv_ids = [] # holds all reservations, a hash with reservation ids as keys and values as the date range of the reservation ### check-out date should not be included - @block_id_and_res_dates = {} + @block_ids = [] @all_dates = [] @blocks_available = [] #block ids that have not been claimed @@ -37,13 +37,12 @@ def reserve_room(check_in_str,check_out_str,reservation_id, guest_id=nil) return false if @all_dates.include?(date) end - @reserv_id_and_dates[reservation_id] = [] - (check_in...check_out).each do |date| - @reserv_id_and_dates[reservation_id] << date + @all_dates << date end - @all_dates = @reserv_id_and_dates.values.flatten + @reserv_ids << reservation_id + ### future note- would it be helpful to sort, and do binary search instead of include? look into it @@ -58,23 +57,15 @@ def reserve_block_room(check_in_str,check_out_str,reservation_id, block_id, gues # # check_in = block.check_in.to_s # check_out = block.check_out.to_s + # + # check_in = Date.parse(check_in_str) + # check_out = Date.parse(check_out_str) - check_in = Date.parse(check_in_str) - check_out = Date.parse(check_out_str) - - check_valid_dates(check_in,check_out) - - raise ArgumentError.new("This room is not available for this block reservation") if !(@blocks_available.include?(block_id)) + # check_valid_dates(check_in,check_out) - (check_in...check_out).each do |date| - raise ArgumentError.new("this room has already been reserved for these dates in this block") if @block_id_and_res_dates[block_id].include?(date) - end + raise ArgumentError.new("This Block room is not available for this block reservation") if !(@blocks_available.include?(block_id)) - #blocks_available.delete(block_id) - - (check_in...check_out).each do |date| - @block_id_and_res_dates[block_id]<< date - end + @blocks_available.delete(block_id) end @@ -90,7 +81,7 @@ def block_room(check_in_str,check_out_str,block_id) return false if @all_dates.include?(date) end - @block_id_and_res_dates[block_id] = [] + @blocks_available << block_id (check_in...check_out).each do |date| @all_dates << date From ed4d23c53bfe238037b67c68263af1d8c973bf66 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Mon, 11 Sep 2017 02:23:02 -0700 Subject: [PATCH 24/27] Refactored all files so that all error handling happened in the Hotel class (booking system); all tests passing --- lib/Block.rb | 11 +- lib/BlockReservation.rb | 6 - lib/Booking.rb | 212 ++++++++++++--------------------- lib/Reservation.rb | 5 +- lib/Room.rb | 160 ++----------------------- specs/BlockReservation_spec.rb | 17 +-- specs/Block_spec.rb | 36 ++++-- specs/Booking_spec.rb | 116 ++++++++++++------ specs/Reservation_spec.rb | 13 +- specs/Room_spec.rb | 160 +++++++------------------ 10 files changed, 252 insertions(+), 484 deletions(-) diff --git a/lib/Block.rb b/lib/Block.rb index 36d7f43ca..0eddc32a2 100644 --- a/lib/Block.rb +++ b/lib/Block.rb @@ -1,4 +1,3 @@ -require 'pry' module HotelBooking class Block @@ -6,16 +5,10 @@ class Block attr_reader :discounted_rate def initialize(check_in,check_out,room_ids,discounted_rate,block_id) - @check_in = Date.parse(check_in) #ruby Date object - @check_out = Date.parse(check_out) #ruby Date object + @check_in = check_in #ruby Date object + @check_out = check_out #ruby Date object @room_ids = room_ids @discounted_rate = discounted_rate - # room_ids.each do |id| - # room = HotelBooking::Hotel.find_room_by_id(id) - # # room.reserve_room(check_in,check_out,@id) - # @rooms << room - # end - @id = block_id end diff --git a/lib/BlockReservation.rb b/lib/BlockReservation.rb index c6d430e9d..ae45d87f8 100644 --- a/lib/BlockReservation.rb +++ b/lib/BlockReservation.rb @@ -1,7 +1,4 @@ - -require_relative 'Block' require_relative 'Reservation' -require_relative 'Booking' module HotelBooking class BlockReservation < HotelBooking::Reservation @@ -10,7 +7,6 @@ class BlockReservation < HotelBooking::Reservation def initialize(check_in,check_out,room_id, b_res_id, block_discount, guest = nil) super(check_in,check_out,room_id, b_res_id,block_discount, guest = nil) - #how do I incorporate a block id? @rate = block_discount @block_id = nil @type= :block @@ -21,5 +17,3 @@ def cost end end end - -#can I have additional parameter block_id, and still use super to inherit from Reservation diff --git a/lib/Booking.rb b/lib/Booking.rb index 04fe79629..7aadabc01 100644 --- a/lib/Booking.rb +++ b/lib/Booking.rb @@ -1,180 +1,142 @@ -### Booking Program class that holds all of the business logic for the hotel and the reservation system require 'date' -require 'pry' require_relative 'Reservation' require_relative 'Room' require_relative 'Block' - -#TODO 09/07/2017:Design logic: Rooms have reservations, have dates, BUT CURRENTLY, Rooms store reservations and all dates on which they are reserved, and that is used to check quickly what rooms are available. -#Rooms also store a hash of Reservation id keys, with their corresponding dates as values, which seems superfluous. RECONSIDER THIS DESIGN. Should Rooms hold Reservation objects only? Reservation objects and dates reserved? maybe just reservation ids and dates? Maybe just reservation ids and helper method that will retrieve the reservation as needed? Think through - -## THINK THROUGH: Does a Room create a Reservation based on availability vs. does a Reservation, once created, reserve a room? - -###Should check for valid inputs in Hotel, instead of checking everywhere? - - -##### if designating reservations by type, maybe a subclass of BlockReservations is not needed unless the behaviors are very different -#### same with room types - - -###TODO: BlockReservations Have Ids that are strings. Consider: should Reservations Also have IDs that are Strings - module HotelBooking - # NUMBER_OF_ROOMS = 20 ### might not want to use constant, especially if we have subclasses of rooms (by type), and each room subclass might have a different number. may best be a constant defined by class/subclass class Hotel attr_reader :all_rooms, :all_reservations, :all_blocks NUM_STANDARD_ROOMS = 20 - #NUM_OTHER_ROOMS = 0 - def initialize # do we want to initialize with hotel name? - # @all_rooms = Hotel::Room.all # returns an array or hash of Room objects + def initialize @all_rooms = HotelBooking::Hotel.setup_rooms @all_reservations = [] @all_blocks = [] - end - ####should this be a Room, self.all method def available_rooms(check_in,check_out, block_id = nil) - #check_in and #check_out are strings - #TODO: below - # confirm check_out date availability logic - #error handling - #message if no rooms are available? - @all_rooms.select {|room| room.available_all_days?(check_in, check_out)} - - #if block_id - end - def find_room_by_id(room_id) - @all_rooms.each {|room| return room if room.id == room_id} - - raise ArgumentError.new "Sorry, we don't have a room matching that ID number." + check_valid_dates(check_in,check_out) + @all_rooms.select {|room| room.available_all_days?(check_in, check_out)} end def make_block(check_in,check_out,room_ids,discounted_rate) + check_in_date = Date.parse(check_in) + check_out_date = Date.parse(check_out) - raise ArgumentError.new("Number of rooms in a block must be 5 or under") if room_ids.count > 5 + check_valid_dates(check_in_date,check_out_date) + check_valid_block(check_in_date,check_out_date,room_ids) - available_rooms_ids = available_rooms(check_in,check_out).map {|room| room.id} + block_id = "B" + "#{@all_blocks.count + 1}" - room_ids.each do |room_id| - raise ArgumentError.new("The room you've selected for this block is not available for this time period.") if !(available_rooms_ids.include?(room_id)) - end + # block_rooms = [] + # + # room_ids.each do |id| + # room = find_room_by_id(id) + # block_rooms << room + # end - block_id = "B" + "#{@all_blocks.count + 1}" - block = HotelBooking::Block.new(check_in,check_out,room_ids,discounted_rate,block_id) + block = HotelBooking::Block.new(check_in_date,check_out_date,room_ids,discounted_rate,block_id) - block.room_ids.each do |room_id| - room = find_room_by_id(room_id) - room.block_room(check_in,check_out,block_id) + room_ids.each do |room_id| + room= find_room_by_id(room_id) + room.block_room(check_in_date,check_out_date,block_id) end @all_blocks << block end + def make_reservation(check_in,check_out,room_id, guest_id=nil) - ###should this be a Room method - def make_reservation(check_in,check_out,room_id, block_id = nil, guest_id=nil) - - reservation_id = (@all_reservations.count + 1) #something + reservation_id = (@all_reservations.count + 1) room= find_room_by_id(room_id) + check_in_date = Date.parse(check_in) + check_out_date = Date.parse(check_out) - if block_id - #TODO: think about whether or not to have a separate block reservation id logic and whether or not to store block reservations in the same place as all reservations AND store them separately, or store them in one place (either all reservations or Block reservations) + check_valid_dates(check_in_date,check_out_date) - #TODO: IMPLEMTN THIS block_reservation_id = "B" + "#{reservation_id}", if decided to convert all reservation IDs to strings + if available_rooms(check_in_date,check_out_date).include?(room) - all_block_ids = @all_blocks.map {|block| block.id} - raise ArgumentError.new("This block doesn't exist") if !(all_block_ids.include?(block_id)) + reservation = HotelBooking::Reservation.new(check_in_date,check_out_date,room_id, reservation_id) - block= find_block_by_id(block_id) - # binding.pry + room.reserve_room(check_in_date,check_out_date,reservation_id, guest_id) - block_discount = block.discounted_rate + @all_reservations << reservation + else + raise ArgumentError.new("This room is already reserved for these dates") + end + end - raise ArgumentError.new("This room is not in the block") if !(block.room_ids.include?(room_id)) + def make_block_reservation(block_id,room_id,guest_id = nil) + reservation_id = (@all_reservations.count + 1) + room= find_room_by_id(room_id) + block= find_block_by_id(block_id) - #TODO: IRON OUT and TEST block reservation constraints: check in and check out MUST be that of the BLOCK check_in/Check_out dates - block_check_in = block.check_in.to_s - block_check_out= block.check_out.to_s + raise ArgumentError.new("This block does not exist") if !(@all_blocks.include?(find_block_by_id(block_id))) + raise ArgumentError.new("This room is not in the block") if !(block.room_ids.include?(room_id)) - #TODO: Think about if we want to make a block reservation id a +1 count of all reservations, or have separate ids for blocks - reservation = HotelBooking::BlockReservation.new(block_check_in,block_check_out,room_id, reservation_id, block_discount) - reservation.block_id = block_id + reservation = HotelBooking::BlockReservation.new(block.check_in,block.check_out,room_id, reservation_id, block.discounted_rate) + reservation.block_id = block_id - room.reserve_block_room(block_check_in,block_check_out,reservation.id, block_id, guest_id=nil) + room.reserve_block_room(block_id,reservation.id, guest_id=nil) - else - reservation = HotelBooking::Reservation.new(check_in,check_out,room_id, reservation_id,block_id) + @all_reservations << reservation - room.reserve_room(check_in,check_out,reservation_id, guest_id) - end + end - # #TODO: How to incorporate reserve_room logic for Block Reservations - # room = find_room_by_id(room_id) - # room.reserve_room(check_in,check_out,reservation.id, guest_id) if reservation.type == :standard + def find_room_by_id(room_id) + @all_rooms.each {|room| return room if room.id == room_id} - # if reservation.type == :block - # - # check_in_str,check_out_str,reservation_id, block_id, guest_id=nil) - # - # room.reserve_block_room(check_in,check_out,reservation.id, block_id, guest_id=nil) - # room.blocks_available.delete(block_id) - # end + raise ArgumentError.new "Sorry, we don't have a room matching that ID number." + end - @all_reservations << reservation + def find_res_by_date(date_str) + date_object= Date.parse(date_str) + @all_reservations.select {|reservation| ((reservation.check_in)..(reservation.check_out)).include?(date_object)} + end + + def find_block_by_id(block_id) + @all_blocks.each {|block| return block if block.id == block_id} + raise ArgumentError.new "Sorry, we don't have a block matching that ID number." end - # def make_block_res(check_in,check_out,room_id, block_id, type = :block, guest_id=nil) - # room= Hotel::Room.find_by_id(room_id) - # block = find_block_by_id(block_id) - # - # raise ArgumentError.new("Error: No block matching that ID number") if !(block) - # raise ArgumentError.new("This room isn't included in your block") if !(room.block_id_and_res_dates.keys.include?(block_id)) - # - # reservation_id = (@all_reservations.count + 1) #something - # reservation = Hotel::Reservation.new(check_in,check_out,room_id, reservation_id,type = :block,guest_id) - # - # - # reservation.room.reserve_room(check_in,check_out,reservation.id, guest_id) - # - # @all_reservations << reservation - # - # - # end + def find_available_rooms_by_block(block_id) + block= find_block_by_id(block_id) + + block_rooms = block.room_ids.map {|id| find_room_by_id(id)} - def find_res_by_date(date_str) - date_object= Date.parse(date_str) - reserved_on_date = [] - @all_reservations.each do |reservation| - room= find_room_by_id(reservation.room_id) + block_rooms.select {|room| room.blocks_available.include?(block_id)} + end - reserved_on_date << reservation if room.all_dates.include?(date_object) - end + def check_valid_block(check_in,check_out,room_ids) + raise ArgumentError.new("Number of rooms in a block must be 5 or under") if room_ids.count > 5 + available_rooms_ids = available_rooms(check_in,check_out).map {|room| room.id} - # {|reservation| reserved_on_date << reservation if reservation.room.all_dates.include?(date_object)} + room_ids.each do |room_id| + raise ArgumentError.new("This room is already reserved for the dates provided") if !(available_rooms_ids.include?(room_id)) + end - return reserved_on_date + return true - #self.all.select {|reservation| reservation.room.all_dates.include?(date_object)} end - def find_block_res_by_block_id(block_id,guest_id=nil ) + def check_valid_dates(check_in, check_out) + if check_in < Date.today || check_out < Date.today + raise ArgumentError.new("Can't make reservations for days earlier than today") + end - end + if check_in.class != Date ||check_out.class != Date + raise ArgumentError.new("Please provide a valid date") + end - def find_block_by_id(block_id) - @all_blocks.each do |block| - return block if block.id == block_id + if check_out < check_in + raise ArgumentError.new("Invalid Date Range: Check out date is earlier than check-in date.") end - return false end def self.setup_rooms @@ -188,30 +150,8 @@ def self.setup_rooms end return standard_rooms - - #can modify to set up for different types of rooms end - - - - - # def find_res_by_guest(guest_id) - # end - # - - # - # def find_res_by_room(room_id) - # end - - #def find_res_by_id(reservation_id) - #end - end end - - -# binding.pry - -#########WAVE 2 ##### diff --git a/lib/Reservation.rb b/lib/Reservation.rb index fb1dddacd..263dd2144 100644 --- a/lib/Reservation.rb +++ b/lib/Reservation.rb @@ -1,4 +1,3 @@ -require 'pry' require 'date' module HotelBooking @@ -8,8 +7,8 @@ class Reservation def initialize(check_in,check_out,room_id, res_id, rate = 200, guest = nil) @id = res_id - @check_in = Date.parse(check_in) #ruby Date object - @check_out = Date.parse(check_out) #ruby Date object + @check_in = check_in #ruby Date object + @check_out = check_out #ruby Date object @room_id= room_id @guest = guest @rate = rate diff --git a/lib/Room.rb b/lib/Room.rb index e3250a2dd..6893d1681 100644 --- a/lib/Room.rb +++ b/lib/Room.rb @@ -1,82 +1,37 @@ -require 'pry' require 'date' -require_relative 'Reservation' -require_relative 'BlockReservation' -require_relative 'Booking' module HotelBooking class Room attr_reader :id, :nightly_rate, :type, :reserv_ids, :all_dates, :block_ids, :blocks_available - # :status - - @@total_num_rooms = 20 def initialize(id_number, nightly_rate = 200) @id = id_number @nightly_rate = nightly_rate - @type = :standard # is this necessary + @type = :standard @reserv_ids = [] - # holds all reservations, a hash with reservation ids as keys and values as the date range of the reservation ### check-out date should not be included @block_ids = [] @all_dates = [] - @blocks_available = [] #block ids that have not been claimed - - # @status = :available #not sure if status is needed anymore.maybe a method, available? - + @blocks_available = [] end - def reserve_room(check_in_str,check_out_str,reservation_id, guest_id=nil) - check_in = Date.parse(check_in_str) - check_out = Date.parse(check_out_str) - - check_valid_dates(check_in,check_out) - - - (check_in...check_out).each do |date| - return false if @all_dates.include?(date) - end + def reserve_room(check_in,check_out,reservation_id, guest_id=nil) (check_in...check_out).each do |date| @all_dates << date end @reserv_ids << reservation_id - - ### future note- would it be helpful to sort, and do binary search instead of include? look into it - - end - def reserve_block_room(check_in_str,check_out_str,reservation_id, block_id, guest_id=nil) - - #TODO: maybe reserve block room should only take in a Block id, since the check-in and check-out dates will be whatever the dates of the block are - - #def reserve_block_room(block_id, reservation_id) - # block = Hotel::BookingProgram.all_blocks.find_block_by_id(block_id) - # - # check_in = block.check_in.to_s - # check_out = block.check_out.to_s - # - # check_in = Date.parse(check_in_str) - # check_out = Date.parse(check_out_str) - - # check_valid_dates(check_in,check_out) - + def reserve_block_room(block_id, reservation_id, guest_id=nil) raise ArgumentError.new("This Block room is not available for this block reservation") if !(@blocks_available.include?(block_id)) @blocks_available.delete(block_id) - - end - def block_room(check_in_str,check_out_str,block_id) - check_in = Date.parse(check_in_str) - check_out = Date.parse(check_out_str) - - check_valid_dates(check_in,check_out) - + def block_room(check_in,check_out,block_id) (check_in...check_out).each do |date| return false if @all_dates.include?(date) end @@ -86,117 +41,16 @@ def block_room(check_in_str,check_out_str,block_id) (check_in...check_out).each do |date| @all_dates << date end - end - def self.all - i = 1 - all_rooms = [] - - until all_rooms.count == @@total_num_rooms - room = HotelBooking::Room.new(i) - all_rooms << room - i += 1 - end - - return all_rooms - end - - - def self.find_by_id(room_id) - self.all.each {|room| return room if room.id == room_id} - - raise ArgumentError.new "Sorry, we don't have a room matching that ID number." - end - - - def available_all_days?(check_in_str, check_out_str) - check_in = Date.parse(check_in_str) - check_out = Date.parse(check_out_str) - - (check_in..check_out).each do |date| ### double check this logic, inclusive rather than exclusive + def available_all_days?(check_in, check_out) + (check_in..check_out).each do |date| return false if @all_dates.include?(date) end return true end - def check_valid_dates(check_in, check_out) - if check_in < Date.today || check_out < Date.today - raise ArgumentError.new("Can't make reservations for days earlier than today") - end - - if check_in.class != Date ||check_out.class != Date - raise ArgumentError.new("Please provide a valid date") - end - - if check_out < check_in - raise ArgumentError.new("Invalid Date Range: Check out date is earlier than check-in date.") - end - - end - end end - -# binding.pry - - -##########Wave 2 - -# def available?(date_str) -# #date format is year, month, day -# date = Date.parse(date_str) -# return false if @all_dates.include?(date) -# return true -# end - -# -# def available_all_days?(check_in_str, check_out_str) -# check_in = Date.parse(check_in_str) -# check_out = Date.parse(check_out_str) -# -# (check_in...check_out).each do |date| -# return false if available?(date) == false -# end -# -# return true -# end - -# def available_all_days?(check_in_str, check_out_str) -# check_in = Date.parse(check_in_str) -# check_out = Date.parse(check_out_str) -# -# (check_in...check_out).each do |date| -# return false if @all_dates.include?(date) -# end -# -# return true -# end - -# def reserve_room(check_in,check_out,res_id, guest_id,room_id) -# if available_all_days?(check_in,check_out) -# reserved_dates[res_id] = (check_in...check_out) #range of dates, maybe stored as array? -# -# end -# -# end - - - - -#BEGIN RESCUE CLAUSE - -# begin -# if check_in < Date.today || check_out < Date.today -# raise ArgumentError.new("Can't make reservations for days earlier than today") -# end -# -# if check_in.class != Date ||check_out.class != Date -# raise ArgumentError.new("Please provide the date in the following format: \n YYYY-MM-DD") -# end - -# rescue ArgumentError => exception -# puts "Encountered an error: #{exception}" -# end diff --git a/specs/BlockReservation_spec.rb b/specs/BlockReservation_spec.rb index 30697425f..cb50089b5 100644 --- a/specs/BlockReservation_spec.rb +++ b/specs/BlockReservation_spec.rb @@ -1,20 +1,21 @@ require 'date' -require 'pry' + require_relative 'spec_helper' describe "HotelBooking::BlockReservation class" do describe "initialize" do - it "initalizes" do - check_in_str = "2018-10-03" - check_out_str = "2018-10-06" + it "initalizes with the appropriate reservation type" do + check_in = Date.parse("2018-10-03") + check_out = Date.parse("2018-10-06") room_id = 1 b_res_id = 14 discounted_rate = 5 block_id = 42 - new_block_res = HotelBooking::BlockReservation.new(check_in_str, check_out_str,room_id,b_res_id,discounted_rate, block_id) + new_block_res = HotelBooking::BlockReservation.new(check_in, check_out,room_id,b_res_id,discounted_rate, block_id) new_block_res.must_be_instance_of HotelBooking::BlockReservation + new_block_res.type.must_equal :block end end @@ -22,7 +23,7 @@ describe "num_nights_charged" do it "correctly inherits the num_nights_charged method from the HotelBooking::Reservation class" do - blockres1 = HotelBooking::BlockReservation.new("2018-02-14", "2018-02-16",3,14,5) + blockres1 = HotelBooking::BlockReservation.new(Date.parse("2018-02-14"), Date.parse("2018-02-16"),3,14,5) blockres1.num_nights_charged.must_equal 2 end @@ -31,10 +32,10 @@ describe "cost" do it "calculates cost with a discounted rate" do discounted_rate = 5 - blockres1 = HotelBooking::BlockReservation.new("2018-02-14", "2018-02-16",14,42,discounted_rate) + blockres1 = HotelBooking::BlockReservation.new(Date.parse("2018-02-14"), Date.parse("2018-02-16"),14,42,discounted_rate) blockres1.cost.must_equal 10 - blockres2 = HotelBooking::BlockReservation.new("2018-12-01", "2018-12-02",1,5,discounted_rate) + blockres2 = HotelBooking::BlockReservation.new(Date.parse("2018-12-01"), Date.parse("2018-12-02"),1,5,discounted_rate) blockres2.cost.must_equal 5 end diff --git a/specs/Block_spec.rb b/specs/Block_spec.rb index 03da31baf..0aeb70988 100644 --- a/specs/Block_spec.rb +++ b/specs/Block_spec.rb @@ -2,22 +2,32 @@ describe "HotelBooking::Block class " do describe "initialize" do - it "initalizes" do - check_in_str = "2018-10-03" - check_out_str = "2018-10-06" - room_ids = [1,2,3] - block_id = "Amy's Party" - discounted_rate = 5 - new_block = HotelBooking::Block.new(check_in_str, check_out_str,room_ids,discounted_rate,block_id) + before do + @check_in_str = "2018-10-03" + @check_out_str = "2018-10-06" + @new_hotel = HotelBooking::Hotel.new + @room_ids= [1,2,3] + @block_id = "Amy's Party" + @discounted_rate = 5 + @new_block = HotelBooking::Block.new(Date.parse(@check_in_str), Date.parse(@check_out_str),@room_ids,@discounted_rate,@block_id) + end - new_block.must_be_instance_of HotelBooking::Block - new_block.room_ids.must_be_instance_of Array - new_block.room_ids.each do |room| - room.must_be_instance_of Integer - end + it "initalizes with attributes that we can access in our booking system" do + @new_block.must_be_instance_of HotelBooking::Block + + @new_block.id.must_equal @block_id + @new_block.check_in.to_s.must_equal @check_in_str + @new_block.check_out.to_s.must_equal @check_out_str - new_block.id.must_equal block_id + end + it "stores an array of room ids " do + @new_block.room_ids.must_be_instance_of Array + @new_block.room_ids.must_equal @room_ids + @new_block.room_ids.each do |id| + id.must_be_instance_of Integer + end end + end end diff --git a/specs/Booking_spec.rb b/specs/Booking_spec.rb index 4410dcd66..a831dbcec 100644 --- a/specs/Booking_spec.rb +++ b/specs/Booking_spec.rb @@ -10,7 +10,6 @@ room.must_be_instance_of HotelBooking::Room end - end end @@ -58,7 +57,10 @@ end - it "makes a BlockReservation object if given a block_id" do + end + + describe "make_block_reservation" do + it "makes a BlockReservation object if given a block id and room id" do new_hotel = HotelBooking::Hotel.new room_id = 3 non_exist_block_id = "B2" @@ -68,7 +70,7 @@ check_in = "2018-11-10" check_out = "2018-11-12" - proc {new_hotel.make_reservation(check_in, check_out, room_id, non_exist_block_id)}.must_raise ArgumentError + proc {new_hotel.make_block_reservation(non_exist_block_id, room_id)}.must_raise ArgumentError new_hotel.make_block(check_in,check_out,rooms_in_block,10) @@ -77,19 +79,13 @@ new_block = new_hotel.all_blocks[0] block_id = new_block.id - proc {new_hotel.make_reservation(check_in,check_out,room_id,non_exist_block_id)}.must_raise ArgumentError - - # binding.pry + new_hotel.make_block_reservation(block_id,room_id) - new_hotel.make_reservation(check_in,check_out,room_id,block_id) + proc {new_hotel.make_block_reservation(block_id,room_id)}.must_raise ArgumentError new_block_reservation = new_hotel.all_reservations[-1] new_block_reservation.block_id.must_equal "B1" - # binding.pry - end - - it "allows another guest to check-in to a room on the same day another guest checks out" do - + new_block_reservation.type.must_equal :block end end @@ -110,7 +106,7 @@ new_block.room_ids.each do |room_id| room = new_hotel.find_room_by_id(room_id) - (Date.parse("2018-03-14")...Date.parse("2018-03-16")).to_a.each do |date| + (Date.parse("2018-03-14")...Date.parse("2018-03-16")).each do |date| room.all_dates.must_include date #fix this logic later end end @@ -149,8 +145,8 @@ describe "available_rooms" do before do @new_hotel = HotelBooking::Hotel.new - @check_in = "June 1, 2018" - @check_out = "June 30, 2018" + @check_in = Date.parse("June 1, 2018") + @check_out = Date.parse("June 30, 2018") @june_rooms = @new_hotel.available_rooms(@check_in, @check_out) end @@ -203,12 +199,11 @@ describe "find_block_by_id" do it "can find the first and last block" do new_hotel = HotelBooking::Hotel.new - # binding.pry - # new_hotel.find_block_by_id(1).must_equal false + proc {new_hotel.find_block_by_id(1)}.must_raise ArgumentError - # binding.pry + room_ids = [3,4,5] - new_hotel.make_block("2018-06-13", "2018-06-15", [3,4,5], 15) + new_hotel.make_block("2018-06-13", "2018-06-15", room_ids, 15) first_block = new_hotel.all_blocks[0] first_block.must_be_instance_of HotelBooking::Block @@ -222,23 +217,6 @@ end - describe "self.setup_rooms" do - it "returns an array of all room objects, with the accurate number of rooms" do - test_all_rooms = HotelBooking::Hotel.setup_rooms - - test_all_rooms.must_be_instance_of Array - - test_all_rooms.each do |room| - room.must_be_instance_of HotelBooking::Room - room.nightly_rate.must_equal 200 - end - - test_all_rooms.count.must_equal 20 - - end - - end #end self.setup_rooms - describe "find_room_by_id" do it "can find the first and last room" do new_hotel = HotelBooking::Hotel.new @@ -259,4 +237,70 @@ last_room.must_equal new_hotel.all_rooms[-1] end end + + describe "find_available_rooms_by_block" do + it "Gives you an array of available rooms in a particular block and updates properly" do + new_hotel = HotelBooking::Hotel.new + rooms_in_block = [1,3,5] + room_id = 3 + non_exist_block_id = "B2" + check_in = "2018-11-10" + check_out = "2018-11-12" + discounted_rate = 10 + + new_hotel.make_block(check_in,check_out,rooms_in_block,discounted_rate) + new_hotel.all_blocks.count.must_equal 1 + + new_block = new_hotel.all_blocks[-1] + block_id = new_block.id + + proc {new_hotel.find_available_rooms_by_block(non_exist_block_id)}.must_raise ArgumentError + + avail_rooms_in_block = new_hotel.find_available_rooms_by_block(block_id) + + avail_rooms_in_block.must_be_instance_of Array + + avail_rooms_in_block.each do |room| + room.must_be_instance_of HotelBooking::Room + room.blocks_available.must_include block_id + end + + avail_rooms_in_block.count.must_equal 3 + + new_hotel.make_block_reservation(block_id, room_id) + + updated_available_rooms_in_block = new_hotel.find_available_rooms_by_block(block_id) + + updated_available_rooms_in_block.count.must_equal 2 + + end + end + + describe "check valid dates " do + before do + @new_hotel = HotelBooking::Hotel.new + end + it "raises an error if the check-out dates is earlier than the check-in date" do + check_in= Date.parse("March 3, 2018") + check_out = Date.parse("February 20, 2018") + + proc { @new_hotel.check_valid_dates(check_in, check_out)}.must_raise ArgumentError + end + + it "Raises an error when given a check-in or check-out date earlier than today" do + + check_in = Date.parse("2016-08-09") + check_out = Date.parse("2016-08-12") + + proc { @new_hotel.check_valid_dates(check_in, check_out)}.must_raise ArgumentError + end + + it "raises an error if given input is not a Date object" do + check_in= 1 + check_out= 100 + + proc { @new_hotel.check_valid_dates(check_in, check_out)}.must_raise ArgumentError + + end + end end diff --git a/specs/Reservation_spec.rb b/specs/Reservation_spec.rb index cb43d0521..84445f51f 100644 --- a/specs/Reservation_spec.rb +++ b/specs/Reservation_spec.rb @@ -4,15 +4,15 @@ describe "initialize" do it "requires five arguments, an id, a guest, a check-in date, a check-out date, and a room" do proc {HotelBooking::Reservation.new}.must_raise ArgumentError - proc {HotelBooking::Reservation.new("Jim Bob", "2018-07-01",5)}.must_raise ArgumentError + proc {HotelBooking::Reservation.new("Jim Bob", Date.parse("2018-07-01"),5)}.must_raise ArgumentError - new_res = HotelBooking::Reservation.new("July 1", "2018-07-03", 5, 14) + new_res = HotelBooking::Reservation.new(Date.parse("July 1"), Date.parse("2018-07-03"), 5, 14) new_res.must_be_instance_of HotelBooking::Reservation end - it "creates a Reservation instance that allows us to read the id, guest, check-in date, check-out date, and room " do - read_res = HotelBooking::Reservation.new("2018-07-01", "2018-07-03", 5,100) + it "creates a Reservation instance that allows us to read the id, guest, check-in date, check-out date, type, and room " do + read_res = HotelBooking::Reservation.new(Date.parse("2018-07-01"), Date.parse("2018-07-03"), 5,100) read_res.must_be_instance_of HotelBooking::Reservation [read_res.check_in, read_res.check_out].each do |date| @@ -23,17 +23,18 @@ read_res.check_out.day.must_equal 3 read_res.id.must_equal 100 read_res.room_id.must_equal 5 + read_res.type.must_equal :standard end end #end initialize tests describe "Cost" do it "Returns an integer value that is the total cost of the reservation" do - reservation = HotelBooking::Reservation.new("2018-02-14", "2018-02-16",5,1) + reservation = HotelBooking::Reservation.new(Date.parse("2018-02-14"), Date.parse("2018-02-16"),5,1) reservation.cost.must_equal 400 - res2 = HotelBooking::Reservation.new("2018-12-01", "2018-12-02", 17,3) + res2 = HotelBooking::Reservation.new(Date.parse("2018-12-01"), Date.parse("2018-12-02"), 17,3) res2.cost.must_equal 200 end diff --git a/specs/Room_spec.rb b/specs/Room_spec.rb index c9b1ffac0..10f236795 100644 --- a/specs/Room_spec.rb +++ b/specs/Room_spec.rb @@ -1,8 +1,6 @@ require 'date' -require 'pry' require_relative 'spec_helper' - describe "HotelBooking::Room class" do describe "initialize" do it "requires one argument, number" do @@ -31,190 +29,124 @@ describe "reserve_room" do it "can reserve a room if given the check-in/out date, reservation id, and guest id" do room = HotelBooking::Room.new(666) - check_in_str = "2018-08-09" - check_out_str = "2018-08-12" + check_in= Date.parse("2018-08-09") + check_out = Date.parse("2018-08-12") - room.reserve_room(check_in_str, check_out_str, 1, 13) + room.reserve_room(check_in, check_out, 1, 13) - (Date.parse(check_in_str)...Date.parse(check_out_str)).each do |date| + (check_in...check_out).each do |date| room.all_dates.must_include date end - room.reserve_room("2018-08-10", "2018-08-11", 42, 16).must_equal false - - check_in_str2 = "2018-09-28" - check_out_str2 = "2018-10-1" + check_in2 = Date.parse("2018-09-28") + check_out2= Date.parse("2018-10-1") - room.reserve_room(check_in_str2, check_out_str2, 8, 23) - (Date.parse(check_in_str2)...Date.parse(check_out_str2)).each do |date| + room.reserve_room(check_in2, check_out2, 8, 23) + (check_in2...check_out2).each do |date| room.all_dates.must_include date end end - it "Raises an error when we try to book a room with a check-in or check-out date earlier than today" do - room = HotelBooking::Room.new(123) - check_in_str = "2016-08-09" - check_out_str = "2016-08-12" - - proc { room.reserve_room(check_in_str, check_out_str, 1, 13)}.must_raise ArgumentError - end - - it "raises an error if the check-in or check-out date is invalid" do - room = HotelBooking::Room.new(123) - check_in_str = "February 30, 2018" - check_out_str = "February 31, 2018" - - proc { room.reserve_room(check_in_str, check_out_str, 1, 13)}.must_raise ArgumentError - - end - - it "raises an error if the check-out dates is earlier than the check-in date" do - room = HotelBooking::Room.new(123) - check_in_str = "March 3, 2018" - check_out_str = "February 20, 2018" - - proc { room.reserve_room(check_in_str, check_out_str, 1, 13)}.must_raise ArgumentError - end - end #end reserve_room - describe "self.all" do - it "returns an array of all room objects, with the accurate number of rooms" do - test_all_rooms = HotelBooking::Room.all - - test_all_rooms.must_be_instance_of Array - - test_all_rooms.each do |room| - room.must_be_instance_of HotelBooking::Room - room.nightly_rate.must_equal 200 - end - - test_all_rooms.count.must_equal 20 - - end - - - - end #end self.all describe "available_all_days?" do it "returns the correct Boolean value" do - room1 = HotelBooking::Room.all[0] + new_hotel = HotelBooking::Hotel.new + room1 = new_hotel.all_rooms[0] - check_in = "2018-03-14" - check_out = "2018-03-18" + check_in = Date.parse("2018-03-14") + check_out = Date.parse("2018-03-18") room1.available_all_days?(check_in, check_out).must_equal true room1.available_all_days?(check_in, check_out).must_be_instance_of TrueClass room1.reserve_room(check_in, check_out, 1, 2) - check_in2 = "2018-03-16" - check_out2= "2018-03-17" + check_in2 = Date.parse("2018-03-16") + check_out2= Date.parse("2018-03-17") room1.available_all_days?(check_in2, check_out2).must_equal false room1.available_all_days?(check_in2, check_out2).must_be_instance_of FalseClass #### can make reservations that check-in on the same day that somebody checks out - check_in3 = "2018-03-18" - check_out3 = "2018-03-21" + check_in3 = Date.parse("2018-03-18") + check_out3 = Date.parse("2018-03-21") room1.available_all_days?(check_in3, check_out3).must_equal true room1.available_all_days?(check_in3, check_out3).must_be_instance_of TrueClass - end - - end #end available_all_days describe "block room" do it "can block a room if given the check-in/out date and block id so that it is unavailable to reserve via regular reservations" do room = HotelBooking::Room.new(666) - check_in_str = "2018-08-09" - check_out_str = "2018-08-12" + check_in = Date.parse("2018-08-09") + check_out = Date.parse("2018-08-12") block_id = 3 - room.block_room(check_in_str, check_out_str, block_id) + room.block_room(check_in, check_out, block_id) - (Date.parse(check_in_str)...Date.parse(check_out_str)).each do |date| + (check_in...check_out).each do |date| room.all_dates.must_include date end - room.reserve_room("2018-08-10", "2018-08-11", 42, 16).must_equal false - - check_in_str2 = "2018-09-28" - check_out_str2 = "2018-10-1" + check_in2 = Date.parse("2018-09-28") + check_out2 = Date.parse("2018-10-1") - room.reserve_room(check_in_str2, check_out_str2, 8, 23) - (Date.parse(check_in_str2)...Date.parse(check_out_str2)).each do |date| + room.reserve_room(check_in2, check_out2, 8, 23) + (check_in2...check_out2).each do |date| room.all_dates.must_include date end end end - xdescribe "reserve_block_room" do - it "can reserve a room if given the check-in/out date, reservation id, and guest id" do - hotel = HotelBooking::BookingProgram.new + describe "reserve_block_room" do + it "can reserve a room in a given block if given the check-in/out date, reservation id, and block id" do + hotel = HotelBooking::Hotel.new rooms_in_block = [1,3] block_room_wanted = 3 - check_in_str = "2018-08-09" - check_out_str = "2018-08-12" + check_in = "2018-08-09" + check_out = "2018-08-12" discounted_rate = 10 - hotel.make_block(check_in_str, check_out_str, rooms_in_block,discounted_rate) + hotel.make_block(check_in, check_out, rooms_in_block,discounted_rate) - block1 = hotel.all_blocks[0] + block1 = hotel.all_blocks[-1] hotel.all_blocks.count.must_equal 1 block1.must_be_instance_of HotelBooking::Block - block1.id.must_equal 1 + block1.id.must_equal "B1" - room = HotelBooking::Room.find_by_id(block_room_wanted) + room = hotel.find_room_by_id(block_room_wanted) - #check for when trying to make a block reservation for a room that is not in the block e.g.proc{room.reserve_block_room(check_in_str, check_out_str, 1, 20)}.must_raise ArgumentError + room.reserve_block_room(block1.id, 99) - room.reserve_block_room(check_in_str, check_out_str, 99, block1.id) - - (Date.parse(check_in_str)...Date.parse(check_out_str)).each do |date| + (block1.check_in...block1.check_out).each do |date| room.all_dates.must_include date end - (Date.parse(check_in_str)...Date.parse(check_out_str)).each do |date| - room.block_id_and_res_dates[block1.id].must_include date - end - - end - - xit "Raises an error when we try to book a room with a check-in or check-out date earlier than today" do - room = HotelBooking::Room.new(123) - check_in_str = "2016-08-09" - check_out_str = "2016-08-12" - - proc { room.reserve_block_room(check_in_str, check_out_str, 1, 13)}.must_raise ArgumentError end - xit "raises an error if the check-in or check-out date is invalid" do - room = HotelBooking::Room.new(123) - check_in_str = "February 30, 2018" - check_out_str = "February 31, 2018" + end #end reserve_block_room - proc { room.reserve_block_room(check_in_str, check_out_str, 1, 13)}.must_raise ArgumentError + describe "self.setup_rooms" do + it "returns an array of all room objects, with the accurate number of rooms" do + test_all_rooms = HotelBooking::Hotel.setup_rooms - end + test_all_rooms.must_be_instance_of Array - xit "raises an error if the check-out dates is earlier than the check-in date" do - room = HotelBooking::Room.new(123) - check_in_str = "March 3, 2018" - check_out_str = "February 20, 2018" + test_all_rooms.each do |room| + room.must_be_instance_of HotelBooking::Room + room.nightly_rate.must_equal 200 + end - proc { room.reserve_block_room(check_in_str, check_out_str, 1, 13)}.must_raise ArgumentError + test_all_rooms.count.must_equal 20 end - - end #end reserve_block_room - + end #end self.setup_rooms end #end HotelBooking::Room class tests From af12b8ab0984f7b7b5e93ed2b2cd4fb3d210c331 Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Fri, 29 Sep 2017 17:30:22 -0700 Subject: [PATCH 25/27] Finished Evaluating Responsibility Activity --- design-activity.md | 69 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 design-activity.md diff --git a/design-activity.md b/design-activity.md new file mode 100644 index 000000000..0d86c8654 --- /dev/null +++ b/design-activity.md @@ -0,0 +1,69 @@ +1. What classes does each implementation include? Are the lists the same? + +Each of the implementations has three classes: CartEntry, ShoppingCart, and Order. The lists are the same. + + +2. Write down a sentence to describe each class. + +CartEntry seems to be any item/purchase you want to put in your cart, and must have a unit price and quantity. A ShoppingCart holds zero or more CartEntries in an array. Orders have a Shopping Cart, and calculate the total price (including Sales Tax) of all of the Cart Entries in the Cart. + +3. How do the classes relate to each other? It might be helpful to draw a diagram on a whiteboard or piece of paper. +Orders have a ShoppingCart which can hold zero or more CartEntries. + +4. What data does each class store? How (if at all) does this differ between the two implementations? + +__A__ +Cart Entry: @unit_price & @quantity instance variables +ShoppingCart: @entries array +Order: SALES_TAX constant, @cart variable that is an instance of ShoppingCart. + +__B__ +Cart Entry: @unit_price and @quantity instance variables +ShoppingCart: @entries array +Order: Constant SALES_TAX, @cart variable that is an instance of ShoppingCart + + +5. What methods does each class have? How (if at all) does this differ between the two implementations? + +__A__ +CartEntry: Initialize method, accessors for @unit_price and @quantity +ShoppingCart: Initialize method, accessor for @entries +Order: Initialize method, total_price method that calculates the sum of the prices of each entry in the @cart, and returns the total_price including SALEX_TAX. + +__B__ +CartEntry: Initialize method, price method that returns the price of each CartEntry +ShoppingCart: Initialize method, price method that returns the sum of the prices of each entry in the @cart. +Order: Initialize method, total_price method that returns the total price, including sales tax, of all of the items in the cart. + + +6. Consider the Order#total_price method. In each implementation: + + Is logic to compute the price delegated to "lower level" classes like ShoppingCart and CartEntry, or is it retained in Order? + + __A__ + The logic to compute the price is retained in Order. + + __B__ + The logic to compute the price is delegated to "lower level" classes like ShoppingCart and CartEntry. + + Does total_price directly manipulate the instance variables of other classes? + + __A__ + If I'm reading the question correctly, total_price directly manipulates instance variables of other classes in implementation A. It must access the entries array of the @cart instance, then iterate over each CartEntry instance to access the unit_price and quantity of each to calculate the price, sum up the prices of each CartEntry instance, then add the SALES_TAX to get the total_price. + + __B__ + No; Implementation B calls the .price method on the @cart, then adds the SALES_TAX to calculate the total_price. + +7. If we decide items are cheaper if bought in bulk, how would this change the code? + +We would have to add logic for the discounted bulk price (e.g. a lower unit_price or some kind of discount that is applied) if someone places a bulk order. We would also have to determine how a bulk order is placed, whether it's a subclass, or if we just add conditionals to our existing + +8. Which implementation is easier to modify? + +Implementation B- classes better follow single responsibility principle and logic is delegated to "low level" classes, and we can better target only the relevant classes and methods for modification without fear of messing up some other code. + +9. Which implementation better adheres to the single responsibility principle? + +Implementation B + +10. Bonus question once you've read Metz ch. 3: Which implementation is more loosely coupled? From a4779d82ff80714b9f9b57a47457818eb13751bc Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Mon, 2 Oct 2017 03:13:18 -0700 Subject: [PATCH 26/27] Refactored to make sure responsibility/logic to reserve a room in a block are in the Block class instead of Room class --- lib/Block.rb | 10 +++++++++- lib/Booking.rb | 40 +++++++++++++++++----------------------- lib/Room.rb | 19 ++++++------------- specs/Block_spec.rb | 33 +++++++++++++++++++++++++++++++++ specs/Booking_spec.rb | 7 ++----- specs/Room_spec.rb | 31 ------------------------------- 6 files changed, 67 insertions(+), 73 deletions(-) diff --git a/lib/Block.rb b/lib/Block.rb index 0eddc32a2..efb7bfbfd 100644 --- a/lib/Block.rb +++ b/lib/Block.rb @@ -1,17 +1,25 @@ module HotelBooking class Block - attr_accessor :id, :guest, :check_in, :check_out, :room_ids + attr_accessor :id, :guest, :check_in, :check_out, :room_ids, :available_rooms attr_reader :discounted_rate def initialize(check_in,check_out,room_ids,discounted_rate,block_id) @check_in = check_in #ruby Date object @check_out = check_out #ruby Date object @room_ids = room_ids + @available_rooms = room_ids.dup @discounted_rate = discounted_rate @id = block_id end + def reserve_block_room(room_id) + raise ArgumentError.new("This Block room is not available for this block reservation") if !(@available_rooms.include?(room_id)) + + @available_rooms.delete(room_id) + end + + end end diff --git a/lib/Booking.rb b/lib/Booking.rb index 7aadabc01..d91f6770e 100644 --- a/lib/Booking.rb +++ b/lib/Booking.rb @@ -1,3 +1,4 @@ + require 'date' require_relative 'Reservation' require_relative 'Room' @@ -5,6 +6,8 @@ module HotelBooking class Hotel + + #The Hotel class holds the data of all rooms, all reservations, and all blocks in the Hotel. It checks for valid dates before creating new reservations, block reservations, and blocks. attr_reader :all_rooms, :all_reservations, :all_blocks NUM_STANDARD_ROOMS = 20 @@ -15,7 +18,6 @@ def initialize end def available_rooms(check_in,check_out, block_id = nil) - check_valid_dates(check_in,check_out) @all_rooms.select {|room| room.available_all_days?(check_in, check_out)} end @@ -24,18 +26,15 @@ def make_block(check_in,check_out,room_ids,discounted_rate) check_in_date = Date.parse(check_in) check_out_date = Date.parse(check_out) + + #checks valid dates check_valid_dates(check_in_date,check_out_date) + + #makes sure all rooms intended for the block are available for the date range provided check_valid_block(check_in_date,check_out_date,room_ids) block_id = "B" + "#{@all_blocks.count + 1}" - # block_rooms = [] - # - # room_ids.each do |id| - # room = find_room_by_id(id) - # block_rooms << room - # end - block = HotelBooking::Block.new(check_in_date,check_out_date,room_ids,discounted_rate,block_id) room_ids.each do |room_id| @@ -70,19 +69,19 @@ def make_reservation(check_in,check_out,room_id, guest_id=nil) end def make_block_reservation(block_id,room_id,guest_id = nil) - reservation_id = (@all_reservations.count + 1) - room= find_room_by_id(room_id) + # room= find_room_by_id(room_id) block= find_block_by_id(block_id) + reservation_id = "B" + (@all_reservations.count + 1).to_s - raise ArgumentError.new("This block does not exist") if !(@all_blocks.include?(find_block_by_id(block_id))) raise ArgumentError.new("This room is not in the block") if !(block.room_ids.include?(room_id)) + raise ArgumentError.new("This Block room has already been reserved") if !(block.available_rooms.include?(room_id)) - reservation = HotelBooking::BlockReservation.new(block.check_in,block.check_out,room_id, reservation_id, block.discounted_rate) - reservation.block_id = block_id + block_reservation = HotelBooking::BlockReservation.new(block.check_in,block.check_out,room_id, reservation_id, block.discounted_rate) + block_reservation.block_id = block_id - room.reserve_block_room(block_id,reservation.id, guest_id=nil) + block.reserve_block_room(room_id) - @all_reservations << reservation + @all_reservations << block_reservation end @@ -105,10 +104,7 @@ def find_block_by_id(block_id) def find_available_rooms_by_block(block_id) block= find_block_by_id(block_id) - - block_rooms = block.room_ids.map {|id| find_room_by_id(id)} - - block_rooms.select {|room| room.blocks_available.include?(block_id)} + block.available_rooms end def check_valid_block(check_in,check_out,room_ids) @@ -140,13 +136,11 @@ def check_valid_dates(check_in, check_out) end def self.setup_rooms - i = 1 standard_rooms = [] - until standard_rooms.count == NUM_STANDARD_ROOMS - room = HotelBooking::Room.new(i) + (1..NUM_STANDARD_ROOMS).each do |num| + room = HotelBooking::Room.new(num) standard_rooms << room - i += 1 end return standard_rooms diff --git a/lib/Room.rb b/lib/Room.rb index 6893d1681..f45542590 100644 --- a/lib/Room.rb +++ b/lib/Room.rb @@ -24,23 +24,16 @@ def reserve_room(check_in,check_out,reservation_id, guest_id=nil) @reserv_ids << reservation_id end - def reserve_block_room(block_id, reservation_id, guest_id=nil) - raise ArgumentError.new("This Block room is not available for this block reservation") if !(@blocks_available.include?(block_id)) - - @blocks_available.delete(block_id) - end - def block_room(check_in,check_out,block_id) - (check_in...check_out).each do |date| - return false if @all_dates.include?(date) - end - - @blocks_available << block_id + if available_all_days?(check_in, check_out) + @blocks_available << block_id - (check_in...check_out).each do |date| - @all_dates << date + (check_in...check_out).each do |date| + @all_dates << date + end end + end def available_all_days?(check_in, check_out) diff --git a/specs/Block_spec.rb b/specs/Block_spec.rb index 0aeb70988..78c9dc8dc 100644 --- a/specs/Block_spec.rb +++ b/specs/Block_spec.rb @@ -30,4 +30,37 @@ end end + + describe "reserve_block_room" do + it "can reserve a room in a given block if given the check-in/out date, reservation id, and block id" do + hotel = HotelBooking::Hotel.new + + rooms_in_block = [1,3] + + block_room_wanted = 3 + + check_in = "2018-08-09" + check_out = "2018-08-12" + discounted_rate = 10 + + hotel.make_block(check_in, check_out, rooms_in_block,discounted_rate) + + block1 = hotel.all_blocks[-1] + + hotel.all_blocks.count.must_equal 1 + block1.must_be_instance_of HotelBooking::Block + block1.id.must_equal "B1" + + + block1.reserve_block_room(block_room_wanted) + + block1.available_rooms.must_equal [1] + + # (block1.check_in...block1.check_out).each do |date| + # room.all_dates.must_include date + # end + + end + + end #end reserve_block_room end diff --git a/specs/Booking_spec.rb b/specs/Booking_spec.rb index a831dbcec..8ae87b23a 100644 --- a/specs/Booking_spec.rb +++ b/specs/Booking_spec.rb @@ -260,18 +260,15 @@ avail_rooms_in_block.must_be_instance_of Array - avail_rooms_in_block.each do |room| - room.must_be_instance_of HotelBooking::Room - room.blocks_available.must_include block_id - end - avail_rooms_in_block.count.must_equal 3 + avail_rooms_in_block.must_equal rooms_in_block new_hotel.make_block_reservation(block_id, room_id) updated_available_rooms_in_block = new_hotel.find_available_rooms_by_block(block_id) updated_available_rooms_in_block.count.must_equal 2 + updated_available_rooms_in_block.must_equal [1,5] end end diff --git a/specs/Room_spec.rb b/specs/Room_spec.rb index 10f236795..339132e2a 100644 --- a/specs/Room_spec.rb +++ b/specs/Room_spec.rb @@ -102,37 +102,6 @@ end end - describe "reserve_block_room" do - it "can reserve a room in a given block if given the check-in/out date, reservation id, and block id" do - hotel = HotelBooking::Hotel.new - - rooms_in_block = [1,3] - - block_room_wanted = 3 - - check_in = "2018-08-09" - check_out = "2018-08-12" - discounted_rate = 10 - - hotel.make_block(check_in, check_out, rooms_in_block,discounted_rate) - - block1 = hotel.all_blocks[-1] - - hotel.all_blocks.count.must_equal 1 - block1.must_be_instance_of HotelBooking::Block - block1.id.must_equal "B1" - - room = hotel.find_room_by_id(block_room_wanted) - - room.reserve_block_room(block1.id, 99) - - (block1.check_in...block1.check_out).each do |date| - room.all_dates.must_include date - end - - end - - end #end reserve_block_room describe "self.setup_rooms" do it "returns an array of all room objects, with the accurate number of rooms" do From aa4b0dd1cfa748ff8dc7f129f20666efbc83e8ab Mon Sep 17 00:00:00 2001 From: Amy Lee Date: Mon, 2 Oct 2017 03:21:07 -0700 Subject: [PATCH 27/27] Added comments about Hotel Design changes made to improve Single Responsibility implementation --- design-activity.md | 5 +++++ lib/Booking.rb | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/design-activity.md b/design-activity.md index 0d86c8654..d91d8cdb3 100644 --- a/design-activity.md +++ b/design-activity.md @@ -1,3 +1,8 @@ +__Hotel Design Changes Made__ +I refactored my Hotel program so that all logic and responsibility for reserving a room in a block was in the Block Class instead of the Room class. This is an improvement because Blocks are a special class that have specific rooms, from which a guest can select to create a Block reservation. Room instances do not need to know if they are in a Block, but a Block must know what Rooms it includes, and which are available for booking. Rooms in a Block have special conditions under which they can be reserved, so it makes more sense to have the responsibility and logic to reserve rooms in a block reside in the more specific Block class rather than the general Room class. + + + 1. What classes does each implementation include? Are the lists the same? Each of the implementations has three classes: CartEntry, ShoppingCart, and Order. The lists are the same. diff --git a/lib/Booking.rb b/lib/Booking.rb index d91f6770e..172d299f8 100644 --- a/lib/Booking.rb +++ b/lib/Booking.rb @@ -69,7 +69,6 @@ def make_reservation(check_in,check_out,room_id, guest_id=nil) end def make_block_reservation(block_id,room_id,guest_id = nil) - # room= find_room_by_id(room_id) block= find_block_by_id(block_id) reservation_id = "B" + (@all_reservations.count + 1).to_s