From 2d583cf3c06bbdd4e1e591e47a97698879d3fda1 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Thu, 19 Jan 2023 22:23:25 +0100 Subject: [PATCH 01/32] Refactors create action. Adjusts tests. Passing. --- app/controllers/api/v1/bookings_controller.rb | 49 ++++++----- .../receive_webhooks_controller.rb | 6 +- app/services/stripe_service.rb | 2 +- spec/requests/api/v1/bookings/post_spec.rb | 82 +++++++++++++------ 4 files changed, 82 insertions(+), 57 deletions(-) diff --git a/app/controllers/api/v1/bookings_controller.rb b/app/controllers/api/v1/bookings_controller.rb index 95d9cb8c..1b918e60 100644 --- a/app/controllers/api/v1/bookings_controller.rb +++ b/app/controllers/api/v1/bookings_controller.rb @@ -78,33 +78,30 @@ def index end def create - booking = Booking.create(booking_params) - if booking.persisted? - host = User.where(nickname: booking.host_nickname) - if host.length == 1 - profile = HostProfile.where(user_id: host[0].id) - user = User.where(id: booking.user_id) - if (booking.dates - find_host_bookings(profile[0].id, booking.id)) == booking.dates - render json: { message: I18n.t("controllers.reusable.create_success") }, status: 200 - BookingsMailer.delay(queue: "bookings_email_notifications").notify_host_create_booking( - host[0], - booking, - user[0] - ) - else - cancel_payment_intent(booking.payment_intent_id) - booking.destroy - render json: { error: [I18n.t("controllers.bookings.create_error_1")] }, status: 422 - end - else - cancel_payment_intent(booking.payment_intent_id) - booking.destroy - render json: { error: [I18n.t("controllers.bookings.create_error_2")] }, status: 422 - end - else - cancel_payment_intent(booking.payment_intent_id) - render json: { error: booking.errors.full_messages }, status: 422 + host = User.find_by(nickname: params[:host_nickname]) + if host.nil? + StripeService.cancel_payment_intent(params[:payment_intent_id]) + render json: { errors: [I18n.t("controllers.bookings.create_error_2")] }, status: 400 and return + end + + if !BookingService.validate_dates(params[:host_nickname], params[:dates].map(&:to_i)) + StripeService.cancel_payment_intent(params[:payment_intent_id]) + render json: { errors: [I18n.t("controllers.bookings.create_error_1")] }, status: 400 and return + end + + booking_to_create = Booking.create(booking_params) + if !booking_to_create.persisted? + StripeService.cancel_payment_intent(params[:payment_intent_id]) + render json: { errors: booking_to_create.errors.full_messages }, status: 400 and return end + + user = User.find(booking_to_create.user_id) + BookingsMailer.delay(queue: "bookings_email_notifications").notify_host_create_booking( + host, + booking_to_create, + user + ) + render json: { message: I18n.t("controllers.reusable.create_success") }, status: 200 end def update diff --git a/app/controllers/api/v1/stripe_actions/receive_webhooks_controller.rb b/app/controllers/api/v1/stripe_actions/receive_webhooks_controller.rb index 9109b402..07ce45ee 100644 --- a/app/controllers/api/v1/stripe_actions/receive_webhooks_controller.rb +++ b/app/controllers/api/v1/stripe_actions/receive_webhooks_controller.rb @@ -71,12 +71,12 @@ def perform host = User.find_by(nickname: host_nickname) if host.nil? - StripeService.webhook_cancel_payment_intent(payment_intent) + StripeService.cancel_payment_intent(payment_intent) return end if !BookingService.validate_dates(host_nickname, dates) - StripeService.webhook_cancel_payment_intent(payment_intent) + StripeService.cancel_payment_intent(payment_intent) return end @@ -92,7 +92,7 @@ def perform user_id: user_id ) if !booking_to_create.persisted? - StripeService.webhook_cancel_payment_intent(payment_intent) + StripeService.cancel_payment_intent(payment_intent) return end diff --git a/app/services/stripe_service.rb b/app/services/stripe_service.rb index 8f2f77e0..86cf0457 100644 --- a/app/services/stripe_service.rb +++ b/app/services/stripe_service.rb @@ -15,7 +15,7 @@ def self.get_webhook_endpoint_secret() end end - def self.webhook_cancel_payment_intent(payment_intent_id) + def self.cancel_payment_intent(payment_intent_id) Stripe.api_key = get_api_key begin diff --git a/spec/requests/api/v1/bookings/post_spec.rb b/spec/requests/api/v1/bookings/post_spec.rb index faf4363b..b58ac4a0 100644 --- a/spec/requests/api/v1/bookings/post_spec.rb +++ b/spec/requests/api/v1/bookings/post_spec.rb @@ -51,24 +51,50 @@ def post_request(req_message, req_host, req_dates) it "sends an email" do expect(Delayed::Job.all.count).to eq 1 end + + it "with relevant email to notify the host" do + expect(Delayed::Job.first.handler).to include("notify_host_create_booking") + end end describe "unsuccessfully" do - describe "if not all fields are filled in" do + describe "if host deletes their account in the proccess" do + before { post_request("Lorem Ipsum is simply dummy text.", "John Doe", [1_562_803_200_000, 1_562_889_600_000]) } + + it "with 400 status" do + expect(response.status).to eq 400 + end + + it "with relevant error" do + expect(json_response["errors"]).to eq [ + "Booking cannot be created because the host requested an account deletion! Please find another host in the results page." + ] + end + + it "with correct number of sent emails" do + expect(Delayed::Job.all.count).to eq 1 + end + + it "with relevant email for Stripe action" do + expect(Delayed::Job.first.handler).to include("notify_orphan_payment_intent_to_cancel") + end + end + + describe "if host already accepted someone else's booking request with similar dates" do before do post_request( - "", + "Lorem Ipsum is simply dummy text.", host_profile.user.nickname, - [1_562_803_200_000, 1_562_889_600_000, 1_562_976_000_000, 1_563_062_400_000, 1_563_148_800_000] + [1_563_168_800_000, 1_563_188_800_000] ) end - it "with 422 status" do - expect(response.status).to eq 422 + it "with 400 status" do + expect(response.status).to eq 400 end it "with relevant error" do - expect(json_response["error"]).to eq ["Message can't be blank"] + expect(json_response["errors"]).to eq ["Someone else just requested to book these days with this host!"] end it "with correct number of sent emails" do @@ -80,53 +106,55 @@ def post_request(req_message, req_host, req_dates) end end - describe "if message length is over 400 characters" do + describe "if not all fields are filled in" do before do post_request( - "Lorem Ipsum is simply" * 101, + "", host_profile.user.nickname, [1_562_803_200_000, 1_562_889_600_000, 1_562_976_000_000, 1_563_062_400_000, 1_563_148_800_000] ) end - it "with 422 status" do - expect(response.status).to eq 422 + it "with 400 status" do + expect(response.status).to eq 400 end it "with relevant error" do - expect(json_response["error"]).to eq ["Message is too long (maximum is 400 characters)"] + expect(json_response["errors"]).to eq ["Message can't be blank"] + end + + it "with correct number of sent emails" do + expect(Delayed::Job.all.count).to eq 1 + end + + it "with relevant email for Stripe action" do + expect(Delayed::Job.first.handler).to include("notify_orphan_payment_intent_to_cancel") end end - describe "if host already accepted someone else's booking request with similar dates" do + describe "if message length is over 400 characters" do before do post_request( - "Lorem Ipsum is simply dummy text.", + "Lorem Ipsum is simply" * 101, host_profile.user.nickname, - [1_563_168_800_000, 1_563_188_800_000] + [1_562_803_200_000, 1_562_889_600_000, 1_562_976_000_000, 1_563_062_400_000, 1_563_148_800_000] ) end - it "with 422 status" do - expect(response.status).to eq 422 + it "with 400 status" do + expect(response.status).to eq 400 end it "with relevant error" do - expect(json_response["error"]).to eq ["Someone else just requested to book these days with this host!"] + expect(json_response["errors"]).to eq ["Message is too long (maximum is 400 characters)"] end - end - - describe "if host deletes their account in the proccess" do - before { post_request("Lorem Ipsum is simply dummy text.", "John Doe", [1_562_803_200_000, 1_562_889_600_000]) } - it "with 422 status" do - expect(response.status).to eq 422 + it "with correct number of sent emails" do + expect(Delayed::Job.all.count).to eq 1 end - it "with relevant error" do - expect(json_response["error"]).to eq [ - "Booking cannot be created because the host requested an account deletion! Please find another host in the results page." - ] + it "with relevant email for Stripe action" do + expect(Delayed::Job.first.handler).to include("notify_orphan_payment_intent_to_cancel") end end From 217ce516ce27a4dd335036a0812dfa2fb1fe4701 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Thu, 19 Jan 2023 22:42:29 +0100 Subject: [PATCH 02/32] Fixes failing contact_us controller spec --- spec/requests/api/v1/contact_us/index_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/requests/api/v1/contact_us/index_spec.rb b/spec/requests/api/v1/contact_us/index_spec.rb index 9af3e12f..18ea5510 100644 --- a/spec/requests/api/v1/contact_us/index_spec.rb +++ b/spec/requests/api/v1/contact_us/index_spec.rb @@ -68,7 +68,7 @@ get "/api/v1/contact_us", params: { name: "John Doe", - email: "test@fakeeeeeemail.com", + email: "test@f.c", message: "Can I order pizza from your website???" } end From f3a8720dd49085c4cccfa903123c94bf83359f44 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Fri, 20 Jan 2023 13:17:53 +0100 Subject: [PATCH 03/32] Refactors update action. Adjusts specs. All passing. --- app/controllers/api/v1/bookings_controller.rb | 103 ++++------ app/services/booking_service.rb | 23 +++ config/locales/en-US.yml | 1 - config/locales/sv-SE.yml | 1 - spec/requests/api/v1/bookings/patch_spec.rb | 191 +++++++++--------- 5 files changed, 162 insertions(+), 157 deletions(-) diff --git a/app/controllers/api/v1/bookings_controller.rb b/app/controllers/api/v1/bookings_controller.rb index 1b918e60..8c59adff 100644 --- a/app/controllers/api/v1/bookings_controller.rb +++ b/app/controllers/api/v1/bookings_controller.rb @@ -105,72 +105,49 @@ def create end def update - Stripe.api_key = - if ENV["OFFICIAL"] == "yes" - Rails.application.credentials.STRIPE_API_KEY_PROD - else - Rails.application.credentials.STRIPE_API_KEY_DEV - end + Stripe.api_key = StripeService.get_api_key booking = Booking.find(params[:id]) - if current_api_v1_user.nickname == booking.host_nickname - user = User.where(id: booking.user_id) - host = User.where(nickname: booking.host_nickname) - profile = HostProfile.where(user_id: host[0].id) - booking.update(status: params[:status], host_message: params[:host_message]) - case - when booking.persisted? == true && booking.host_message.length < 201 && booking.status == "accepted" - if (booking.dates - find_host_bookings(profile[0].id, booking.id)) == booking.dates - begin - !Rails.env.test? && Stripe::PaymentIntent.capture(booking.payment_intent_id) - render json: { message: I18n.t("controllers.bookings.update_success") }, status: 200 - booking.update( - host_description: profile[0].description, - host_full_address: profile[0].full_address, - host_real_lat: profile[0].latitude, - host_real_long: profile[0].longitude, - host_profile_id: profile[0].id - ) - new_availability = profile[0].availability - booking.dates - profile.update(availability: new_availability) - BookingsMailer.delay(queue: "bookings_email_notifications").notify_user_accepted_booking( - host[0], - booking, - user[0] - ) - rescue Stripe::StripeError - booking.update(status: "pending", host_message: nil) - render json: { error: I18n.t("controllers.reusable.stripe_error") }, status: 555 - end - else - render json: { error: I18n.t("controllers.bookings.update_error_same_dates") }, status: 427 - booking.update( - status: "canceled", - host_message: - "This booking got canceled by KattBNB. The host has accepted another booking in that date range." - ) - BookingsMailer.delay(queue: "bookings_email_notifications").notify_user_declined_booking( - host[0], - booking, - user[0] - ) - cancel_payment_intent(booking.payment_intent_id) - end - when booking.persisted? == true && booking.host_message.length < 201 && booking.status == "declined" - render json: { message: I18n.t("controllers.bookings.update_success") }, status: 200 - BookingsMailer.delay(queue: "bookings_email_notifications").notify_user_declined_booking( - host[0], - booking, - user[0] - ) - cancel_payment_intent(booking.payment_intent_id) - else - render json: { error: booking.errors.full_messages }, status: 422 - end - else - render json: { error: I18n.t("controllers.reusable.update_error") }, status: 422 + + if current_api_v1_user.nickname != booking.host_nickname + render json: { errors: [I18n.t("controllers.reusable.update_error")] }, status: 400 and return + end + + booking.update(status: params[:status], host_message: params[:host_message]) + + if booking.errors.full_messages.length > 0 + render json: { errors: booking.errors.full_messages }, status: 400 and return + end + + user = User.find(booking.user_id) + host = User.find_by(nickname: booking.host_nickname) + profile = HostProfile.find_by(user_id: host.id) + + if booking.status == "declined" + StripeService.cancel_payment_intent(booking.payment_intent_id) + BookingsMailer.delay(queue: "bookings_email_notifications").notify_user_declined_booking(host, booking, user) + render json: { message: I18n.t("controllers.bookings.update_success") }, status: 200 and return + end + + begin + !Rails.env.test? && Stripe::PaymentIntent.capture(booking.payment_intent_id) + BookingService.cancel_same_date_pending_bookings_on_upate(host, booking.dates, booking.id) + booking.update( + host_description: profile.description, + host_full_address: profile.full_address, + host_real_lat: profile.latitude, + host_real_long: profile.longitude, + host_profile_id: profile.id + ) + new_availability = profile.availability - booking.dates + profile.update(availability: new_availability) + BookingsMailer.delay(queue: "bookings_email_notifications").notify_user_accepted_booking(host, booking, user) + render json: { message: I18n.t("controllers.bookings.update_success") }, status: 200 + rescue Stripe::StripeError + booking.update(status: "pending", host_message: nil) + render json: { errors: [I18n.t("controllers.reusable.stripe_error")] }, status: 400 end rescue ActiveRecord::RecordNotFound - render json: { error: [I18n.t("controllers.bookings.update_error")] }, status: :not_found + render json: { errors: [I18n.t("controllers.bookings.update_error")] }, status: 400 end private diff --git a/app/services/booking_service.rb b/app/services/booking_service.rb index a63c396d..68123f90 100644 --- a/app/services/booking_service.rb +++ b/app/services/booking_service.rb @@ -10,4 +10,27 @@ def self.validate_dates(host_nickname, booking_dates) end booking_dates - host_booked_dates.flatten.sort == booking_dates end + + def self.cancel_same_date_pending_bookings_on_upate(host, booking_to_update_dates, booking_to_update_id) + host_bookings = Booking.where(host_nickname: host.nickname, status: "pending") + + if !host_bookings.empty? + host_bookings.each do |host_booking| + if booking_to_update_dates - host_booking.dates != booking_to_update_dates + host_booking.update( + status: "canceled", + host_message: + "This booking got canceled by KattBNB. The host has accepted another booking in that date range." + ) + StripeService.cancel_payment_intent(host_booking.payment_intent_id) + BookingsMailer.delay(queue: "bookings_email_notifications").notify_user_declined_booking( + host, + host_booking, + User.find(host_booking.user_id) + ) + print "Host's #{host.nickname} pending booking with id #{host_booking.id} was canceled by the system cause of same dates with accepted booking with id #{booking_to_update_id}" + end + end + end + end end diff --git a/config/locales/en-US.yml b/config/locales/en-US.yml index 96f07334..dbb93832 100644 --- a/config/locales/en-US.yml +++ b/config/locales/en-US.yml @@ -16,7 +16,6 @@ en-US: create_error_2: "Booking cannot be created because the host requested an account deletion! Please find another host in the results page." update_success: "You have successfully updated this booking!" update_error: "We cannot update this booking because the user requested an account deletion! Please go back to your bookings page." - update_error_same_dates: "You have already accepted a booking in that date range. This one will be canceled and we will notify the user." conversations: create_exists: "Conversation already exists!" update_success: "Success!" diff --git a/config/locales/sv-SE.yml b/config/locales/sv-SE.yml index d3f4ce81..f709b2a5 100644 --- a/config/locales/sv-SE.yml +++ b/config/locales/sv-SE.yml @@ -16,7 +16,6 @@ sv-SE: create_error_2: "Bokningsförfrågan kunde inte skapas eftersom kattvakten begärde att kontot skulle raderas! Vänligen hitta en annan kvattvakt på resultatsidan." update_success: "Du har nu uppdaterat den här bokningen!" update_error: "Vi kunde inte uppdatera denna bokning eftersom användaren begärde att få sitt konto raderat! Vänligen återvänd till din bokningssida." - update_error_same_dates: "Du har redan accepterat en bokning inom det datumintervallet. Den här kommer att avbokas och vi kommer att meddela användaren." conversations: create_exists: "Konversation finns redan!" update_success: "Uppdatering lyckades!" diff --git a/spec/requests/api/v1/bookings/patch_spec.rb b/spec/requests/api/v1/bookings/patch_spec.rb index d7286ffe..a83be46b 100644 --- a/spec/requests/api/v1/bookings/patch_spec.rb +++ b/spec/requests/api/v1/bookings/patch_spec.rb @@ -14,28 +14,36 @@ let(:credentials_cat_owner) { cat_owner.create_new_auth_token } let(:headers_cat_owner) { { HTTP_ACCEPT: "application/json" }.merge!(credentials_cat_owner) } + let(:random_user) { FactoryBot.create(:user) } + let(:booking) do FactoryBot.create( :booking, host_nickname: host.nickname, user_id: cat_owner.id, - dates: [1_562_803_200_000, 1_563_062_400_000] + dates: [1_562_803_200_000, 1_563_062_400_000], + status: "pending" ) end - let!(:accepted_booking) do + let!(:booking_to_cancel) do FactoryBot.create( :booking, host_nickname: host.nickname, - host_profile_id: host_profile.id, - user_id: cat_owner.id, - status: "accepted", - dates: [1_662_976_000_000, 2_662_976_000_000] + user_id: random_user.id, + dates: [1_563_062_400_000], + status: "pending" ) end - let(:cancelled_booking) do - FactoryBot.create(:booking, host_nickname: host.nickname, user_id: cat_owner.id, dates: [1_662_976_000_000]) + let!(:booking_not_to_cancel) do + FactoryBot.create( + :booking, + host_nickname: host.nickname, + user_id: random_user.id, + dates: [1_573_062_400_000, 1_583_062_400_000], + status: "pending" + ) end let(:unauthenticated_headers) { { HTTP_ACCEPT: "application/json" } } @@ -50,11 +58,10 @@ def patch_request(book_id, book_status, book_message, book_headers) end describe "succesfully" do - describe "when host accepts" do + describe "when host declines" do before do - patch_request(booking.id, "accepted", "yeah baby!!!! cat wars!", headers_host) + patch_request(booking.id, "declined", "sorry", headers_host) booking.reload - host_profile.reload end it "with 200 status" do @@ -66,46 +73,33 @@ def patch_request(book_id, book_status, book_message, book_headers) end it "with correct booking status" do - expect(booking.status).to eq "accepted" - end - - it "with correct booking host_message" do - expect(booking.host_message).to eq "yeah baby!!!! cat wars!" - end - - it "with correct booking host_description" do - expect(booking.host_description).to eq host_profile.description - end - - it "with correct booking host_full_address" do - expect(booking.host_full_address).to eq host_profile.full_address - end - - it "with correct booking host_real_lat" do - expect(booking.host_real_lat).to eq host_profile.latitude + expect(booking.status).to eq "declined" end - it "with correct booking host_real_long" do - expect(booking.host_real_long).to eq host_profile.longitude + it "with correct booking host message" do + expect(booking.host_message).to eq "sorry" end - it "with updated host profile availability" do - expect(host_profile.availability).to eq [1_563_148_800_000] + it "with correct number of emails sent" do + expect(Delayed::Job.all.count).to eq 2 end - it "with correct number of emails sent" do - expect(Delayed::Job.all.count).to eq 1 + it "with email to user about declined booking" do + expect(Delayed::Job.last.handler.include?("notify_user_declined_booking")).to eq true end - it "with email to user about accepted booking" do - expect(Delayed::Job.first.handler.include?("notify_user_accepted_booking")).to eq true + it "with email to KattBNB about Stripe payment intent" do + expect(Delayed::Job.first.handler.include?("notify_orphan_payment_intent_to_cancel")).to eq true end end - describe "when host declines" do + describe "when host accepts" do before do - patch_request(booking.id, "declined", "sorry", headers_host) + patch_request(booking.id, "accepted", "yeah baby!!!! cat wars!", headers_host) booking.reload + booking_to_cancel.reload + booking_not_to_cancel.reload + host_profile.reload end it "with 200 status" do @@ -117,99 +111,103 @@ def patch_request(book_id, book_status, book_message, book_headers) end it "with correct booking status" do - expect(booking.status).to eq "declined" + expect(booking.status).to eq "accepted" end - it "with correct booking host_message" do - expect(booking.host_message).to eq "sorry" + it "with correct booking host message" do + expect(booking.host_message).to eq "yeah baby!!!! cat wars!" end - it "with correct number of emails sent" do - expect(Delayed::Job.all.count).to eq 2 + it "with correct booking host description" do + expect(booking.host_description).to eq host_profile.description end - it "with email to user about declined booking" do - expect(Delayed::Job.first.handler.include?("notify_user_declined_booking")).to eq true + it "with correct booking host full address" do + expect(booking.host_full_address).to eq host_profile.full_address end - it "with email to KattBNB about Stripe payment intent" do - expect(Delayed::Job.last.handler.include?("notify_orphan_payment_intent_to_cancel")).to eq true + it "with correct booking host real lat" do + expect(booking.host_real_lat).to eq host_profile.latitude end - end - end - describe "unsuccessfully" do - describe "if another booking has already been accepted on the same date range" do - before do - patch_request(cancelled_booking.id, "accepted", "glad to be of assistance!", headers_host) - cancelled_booking.reload + it "with correct booking host real long" do + expect(booking.host_real_long).to eq host_profile.longitude end - it "with 427 status" do - expect(response.status).to eq 427 + it "with correct booking host profile id" do + expect(booking.host_profile_id).to eq host_profile.id end - it "with relevant error" do - expect( - json_response["error"] - ).to eq "You have already accepted a booking in that date range. This one will be canceled and we will notify the user." + it "with updated host profile availability" do + expect(host_profile.availability).to eq [1_563_148_800_000] end it "with correct number of emails sent" do - expect(Delayed::Job.all.count).to eq 2 + expect(Delayed::Job.all.count).to eq 3 end - it "with email to user about declined booking" do - expect(Delayed::Job.first.handler.include?("notify_user_declined_booking")).to eq true + it "with email to KattBNB about stripe payment intent" do + expect(Delayed::Job.first.handler.include?("notify_orphan_payment_intent_to_cancel")).to eq true end - it "with email to KattBNB about Stripe payment intent" do - expect(Delayed::Job.last.handler.include?("notify_orphan_payment_intent_to_cancel")).to eq true + it "with email to other user about declined booking" do + expect(Delayed::Job.second.handler.include?("notify_user_declined_booking")).to eq true + end + + it "with email to user about accepted booking" do + expect(Delayed::Job.last.handler.include?("notify_user_accepted_booking")).to eq true end - it "with correct status on booking" do - expect(cancelled_booking.status).to eq "canceled" + it "with pending booking with same dates now canceled" do + expect(booking_to_cancel.status).to eq "canceled" end - it "with correct message on booking" do + it "with now canceled booking having the correct system host message" do expect( - cancelled_booking.host_message + booking_to_cancel.host_message ).to eq "This booking got canceled by KattBNB. The host has accepted another booking in that date range." end - end - describe "if host_message is over 200 characters" do - before do - patch_request(booking.id, "accepted", "accepted by host" * 15, headers_host) - booking.reload + it "with pending booking without same dates not affected" do + expect(booking_not_to_cancel.status).to eq "pending" end - it "with 422 status" do - expect(response.status).to eq 422 + it "with correct log message for canceled booking" do + expect(@std_output).to match( + "Host's #{host.nickname} pending booking with id #{booking_to_cancel.id} was canceled by the system cause of same dates with accepted booking with id #{booking.id}" + ) end - it "with relevant error" do - expect(json_response["error"]).to eq ["Host message is too long (maximum is 200 characters)"] + it "with correct log message for stripe error" do + expect(@std_output).to match("No such payment_intent:") end + end + end - it "with correct booking status" do - expect(booking.status).to eq "pending" + describe "unsuccessfully" do + describe "if booking does not exist" do + before { patch_request(200_000, "accepted", "accepted by host", headers_host) } + + it "with 400 status" do + expect(response.status).to eq 400 end - it "with no host_message" do - expect(booking.host_message).to eq nil + it "with relevant error" do + expect(json_response["errors"]).to eq [ + "We cannot update this booking because the user requested an account deletion! Please go back to your bookings page." + ] end end describe "if action comes from the user that primarily requested the booking / an unassociated host" do before { patch_request(booking.id, "accepted", "accepted by host", headers_cat_owner) } - it "with 422 status" do - expect(response.status).to eq 422 + it "with 400 status" do + expect(response.status).to eq 400 end it "with relevant error" do - expect(json_response["error"]).to eq "You cannot perform this action!" + expect(json_response["errors"]).to eq ["You cannot perform this action!"] end end @@ -225,17 +223,26 @@ def patch_request(book_id, book_status, book_message, book_headers) end end - describe "if booking does not exist" do - before { patch "/api/v1/bookings/2000000000", headers: headers_cat_owner } + describe "if host_message is over 200 characters" do + before do + patch_request(booking.id, "accepted", "accepted by host" * 15, headers_host) + booking.reload + end - it "with custom 404 status" do - expect(response.status).to eq 404 + it "with 400 status" do + expect(response.status).to eq 400 end it "with relevant error" do - expect(json_response["error"]).to eq [ - "We cannot update this booking because the user requested an account deletion! Please go back to your bookings page." - ] + expect(json_response["errors"]).to eq ["Host message is too long (maximum is 200 characters)"] + end + + it "with correct booking status" do + expect(booking.status).to eq "pending" + end + + it "with no host message" do + expect(booking.host_message).to eq nil end end end From 8786dd674f26ab7d0b03d39656aad5ca8146c443 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Fri, 20 Jan 2023 13:22:23 +0100 Subject: [PATCH 04/32] Adds equality in date check --- app/services/booking_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/booking_service.rb b/app/services/booking_service.rb index 68123f90..f2c8b03f 100644 --- a/app/services/booking_service.rb +++ b/app/services/booking_service.rb @@ -6,7 +6,7 @@ def self.validate_dates(host_nickname, booking_dates) host_booked_dates = [] host_bookings.each do |host_booking| - host_booking.dates.last > DateService.get_js_epoch && host_booked_dates.push(host_booking.dates) + host_booking.dates.last >= DateService.get_js_epoch && host_booked_dates.push(host_booking.dates) end booking_dates - host_booked_dates.flatten.sort == booking_dates end From a4f54f189bbcd9c276f6ee6714d66dc792fdc836 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Tue, 24 Jan 2023 10:14:41 +0100 Subject: [PATCH 05/32] Creates new namespace and endpoint for incoming booking stats. Adds specs. Passing. --- .../incoming_stats_controller.rb | 26 ++++++ config/routes.rb | 4 + .../incoming_stats/index_spec.rb | 89 +++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 app/controllers/api/v1/fetch_booking_actions/incoming_stats_controller.rb create mode 100644 spec/requests/api/v1/fetch_booking_actions/incoming_stats/index_spec.rb diff --git a/app/controllers/api/v1/fetch_booking_actions/incoming_stats_controller.rb b/app/controllers/api/v1/fetch_booking_actions/incoming_stats_controller.rb new file mode 100644 index 00000000..5691d45e --- /dev/null +++ b/app/controllers/api/v1/fetch_booking_actions/incoming_stats_controller.rb @@ -0,0 +1,26 @@ +class Api::V1::FetchBookingActions::IncomingStatsController < ApplicationController + before_action :authenticate_api_v1_user!, only: %i[index] + + def index + render json: [], status: 200 and return if current_api_v1_user.host_profile.nil? + + pending_bookings = Booking.where(status: "pending", host_nickname: current_api_v1_user.nickname).size + unpaid_bookings = Booking.where(status: "accepted", host_nickname: current_api_v1_user.nickname, paid: false).size + history_bookings_declined_canceled = + Booking.where(status: %w[declined canceled], host_nickname: current_api_v1_user.nickname).size + accepted_bookings = Booking.where(status: "accepted", host_nickname: current_api_v1_user.nickname).select("dates") + + upcoming_bookings = accepted_bookings.select { |booking| booking.dates.last >= DateService.get_js_epoch }.size + history_bookings_accepted = accepted_bookings.size - upcoming_bookings + + render json: { + stats: { + in_requests: pending_bookings, + in_upcoming: upcoming_bookings, + in_history: history_bookings_accepted + history_bookings_declined_canceled, + in_unpaid: unpaid_bookings + } + }, + status: 200 + end +end diff --git a/config/routes.rb b/config/routes.rb index dd9e74a2..a4ee33a2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -20,6 +20,10 @@ resources :reviews, only: [:index] end + namespace :fetch_booking_actions do + resources :incoming_stats, only: [:index] + end + namespace :stripe_actions do resources :retrieve_account_details, only: [:index] resources :retrieve_account_login_link, only: [:index] diff --git a/spec/requests/api/v1/fetch_booking_actions/incoming_stats/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/incoming_stats/index_spec.rb new file mode 100644 index 00000000..f528f9ae --- /dev/null +++ b/spec/requests/api/v1/fetch_booking_actions/incoming_stats/index_spec.rb @@ -0,0 +1,89 @@ +RSpec.describe "GET /api/v1/fetch_booking_actions/incoming_stats", type: :request do + let(:host_profile) { FactoryBot.create(:host_profile) } + let(:host_credentials) { host_profile.user.create_new_auth_token } + let(:host_headers) { { HTTP_ACCEPT: "application/json" }.merge!(host_credentials) } + + let(:random_user) { FactoryBot.create(:user) } + let(:random_user_credentials) { random_user.create_new_auth_token } + let(:random_user_headers) { { HTTP_ACCEPT: "application/json" }.merge!(random_user_credentials) } + + let!(:upcoming_booking) do + FactoryBot.create( + :booking, + host_nickname: host_profile.user.nickname, + host_profile_id: host_profile.id, + status: "accepted", + paid: false, + dates: [1, 2, 3, 2_562_889_600_000] + ) + end + + let!(:history_accepted_booking) do + FactoryBot.create( + :booking, + host_nickname: host_profile.user.nickname, + host_profile_id: host_profile.id, + status: "accepted", + paid: true, + dates: [4, 5, 6, 1_162_889_600_000] + ) + end + + let!(:pending_booking) do + FactoryBot.create(:booking, status: "pending", host_nickname: host_profile.user.nickname, paid: false) + end + + let!(:history_declined_booking) do + FactoryBot.create(:booking, status: "declined", host_nickname: host_profile.user.nickname, paid: false) + end + + let!(:history_cenceled_booking) do + FactoryBot.create(:booking, status: "canceled", host_nickname: host_profile.user.nickname, paid: false) + end + + let!(:random_booking) { FactoryBot.create(:booking, status: "pending") } + + let(:unauthenticated_headers) { { HTTP_ACCEPT: "application/json" } } + + describe "successfully" do + describe "when user has host profile" do + before { get "/api/v1/fetch_booking_actions/incoming_stats", headers: host_headers } + + it "with 200 status" do + expect(response.status).to eq 200 + end + + it "with correct booking stats" do + expect( + json_response["stats"].to_json + ).to eq "{\"in_requests\":1,\"in_upcoming\":1,\"in_history\":3,\"in_unpaid\":1}" + end + end + + describe "when user has no host profile" do + before { get "/api/v1/fetch_booking_actions/incoming_stats", headers: random_user_headers } + + it "with 200 status" do + expect(response.status).to eq 200 + end + + it "with empty collection in the response" do + expect(json_response.size).to eq 0 + end + end + end + + describe "unsuccessfully" do + describe "if user is not logged in" do + before { get "/api/v1/fetch_booking_actions/incoming_stats", headers: unauthenticated_headers } + + it "with 401 status" do + expect(response.status).to eq 401 + end + + it "with relevant error" do + expect(json_response["errors"]).to eq ["You need to sign in or sign up before continuing."] + end + end + end +end From 74cf41f193d08f38d14b8d149e63f7661accbcf3 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Tue, 24 Jan 2023 10:53:37 +0100 Subject: [PATCH 06/32] Creates new endpoint for outgoing booking stats. Adds specs. Passing. --- .../outgoing_stats_controller.rb | 22 +++++++++ config/routes.rb | 1 + .../outgoing_stats/index_spec.rb | 46 +++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 app/controllers/api/v1/fetch_booking_actions/outgoing_stats_controller.rb create mode 100644 spec/requests/api/v1/fetch_booking_actions/outgoing_stats/index_spec.rb diff --git a/app/controllers/api/v1/fetch_booking_actions/outgoing_stats_controller.rb b/app/controllers/api/v1/fetch_booking_actions/outgoing_stats_controller.rb new file mode 100644 index 00000000..0e04073b --- /dev/null +++ b/app/controllers/api/v1/fetch_booking_actions/outgoing_stats_controller.rb @@ -0,0 +1,22 @@ +class Api::V1::FetchBookingActions::OutgoingStatsController < ApplicationController + before_action :authenticate_api_v1_user!, only: %i[index] + + def index + pending_bookings = Booking.where(status: "pending", user_id: current_api_v1_user.id).size + history_bookings_declined_canceled = + Booking.where(status: %w[declined canceled], user_id: current_api_v1_user.id).size + accepted_bookings = Booking.where(status: "accepted", user_id: current_api_v1_user.id).select("dates") + + upcoming_bookings = accepted_bookings.select { |booking| booking.dates.last >= DateService.get_js_epoch }.size + history_bookings_accepted = accepted_bookings.size - upcoming_bookings + + render json: { + stats: { + out_requests: pending_bookings, + out_upcoming: upcoming_bookings, + out_history: history_bookings_accepted + history_bookings_declined_canceled + } + }, + status: 200 + end +end diff --git a/config/routes.rb b/config/routes.rb index a4ee33a2..9bc4f272 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -22,6 +22,7 @@ namespace :fetch_booking_actions do resources :incoming_stats, only: [:index] + resources :outgoing_stats, only: [:index] end namespace :stripe_actions do diff --git a/spec/requests/api/v1/fetch_booking_actions/outgoing_stats/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/outgoing_stats/index_spec.rb new file mode 100644 index 00000000..709a0fed --- /dev/null +++ b/spec/requests/api/v1/fetch_booking_actions/outgoing_stats/index_spec.rb @@ -0,0 +1,46 @@ +RSpec.describe "GET /api/v1/fetch_booking_actions/outgoing_stats", type: :request do + let(:user) { FactoryBot.create(:user) } + let(:user_credentials) { user.create_new_auth_token } + let(:user_headers) { { HTTP_ACCEPT: "application/json" }.merge!(user_credentials) } + + let!(:upcoming_booking) do + FactoryBot.create(:booking, user_id: user.id, status: "accepted", dates: [1, 2, 3, 2_562_889_600_000]) + end + + let!(:history_accepted_booking) do + FactoryBot.create(:booking, user_id: user.id, status: "accepted", dates: [4, 5, 6, 1_162_889_600_000]) + end + + let!(:pending_booking) { FactoryBot.create(:booking, status: "pending", user_id: user.id) } + let!(:history_declined_booking) { FactoryBot.create(:booking, status: "declined", user_id: user.id) } + let!(:history_cenceled_booking) { FactoryBot.create(:booking, status: "canceled", user_id: user.id) } + let!(:random_booking) { FactoryBot.create(:booking, status: "pending") } + + let(:unauthenticated_headers) { { HTTP_ACCEPT: "application/json" } } + + describe "successfully" do + before { get "/api/v1/fetch_booking_actions/outgoing_stats", headers: user_headers } + + it "with 200 status" do + expect(response.status).to eq 200 + end + + it "with correct booking stats" do + expect(json_response["stats"].to_json).to eq "{\"out_requests\":1,\"out_upcoming\":1,\"out_history\":3}" + end + end + + describe "unsuccessfully" do + describe "if user is not logged in" do + before { get "/api/v1/fetch_booking_actions/outgoing_stats", headers: unauthenticated_headers } + + it "with 401 status" do + expect(response.status).to eq 401 + end + + it "with relevant error" do + expect(json_response["errors"]).to eq ["You need to sign in or sign up before continuing."] + end + end + end +end From 9c492664f4e2cf8f87eb3755400c3a23e53f25aa Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Tue, 24 Jan 2023 12:53:18 +0100 Subject: [PATCH 07/32] Creates new endpoint to return host unavailable dates. Adds specs. Passing. --- .../host_unavailable_dates_controller.rb | 9 +++ app/services/booking_service.rb | 12 ++++ config/routes.rb | 1 + .../host_unavailable_dates/index_spec.rb | 69 +++++++++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 app/controllers/api/v1/fetch_booking_actions/host_unavailable_dates_controller.rb create mode 100644 spec/requests/api/v1/fetch_booking_actions/host_unavailable_dates/index_spec.rb diff --git a/app/controllers/api/v1/fetch_booking_actions/host_unavailable_dates_controller.rb b/app/controllers/api/v1/fetch_booking_actions/host_unavailable_dates_controller.rb new file mode 100644 index 00000000..0457186e --- /dev/null +++ b/app/controllers/api/v1/fetch_booking_actions/host_unavailable_dates_controller.rb @@ -0,0 +1,9 @@ +class Api::V1::FetchBookingActions::HostUnavailableDatesController < ApplicationController + before_action :authenticate_api_v1_user!, only: %i[index] + + def index + render json: [], status: 200 and return if current_api_v1_user.host_profile.nil? + + render json: BookingService.get_host_unavailable_dates(current_api_v1_user.host_profile.id), status: 200 + end +end diff --git a/app/services/booking_service.rb b/app/services/booking_service.rb index f2c8b03f..b062b9b8 100644 --- a/app/services/booking_service.rb +++ b/app/services/booking_service.rb @@ -11,6 +11,18 @@ def self.validate_dates(host_nickname, booking_dates) booking_dates - host_booked_dates.flatten.sort == booking_dates end + def self.get_host_unavailable_dates(host_profile_id) + host_bookings = Booking.where(status: "accepted", host_profile_id: host_profile_id) + + return [] if host_bookings.empty? + + host_booked_dates = [] + host_bookings.each do |host_booking| + host_booking.dates.last >= DateService.get_js_epoch && host_booked_dates.push(host_booking.dates) + end + host_booked_dates.flatten.sort + end + def self.cancel_same_date_pending_bookings_on_upate(host, booking_to_update_dates, booking_to_update_id) host_bookings = Booking.where(host_nickname: host.nickname, status: "pending") diff --git a/config/routes.rb b/config/routes.rb index 9bc4f272..03488612 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -23,6 +23,7 @@ namespace :fetch_booking_actions do resources :incoming_stats, only: [:index] resources :outgoing_stats, only: [:index] + resources :host_unavailable_dates, only: [:index] end namespace :stripe_actions do diff --git a/spec/requests/api/v1/fetch_booking_actions/host_unavailable_dates/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/host_unavailable_dates/index_spec.rb new file mode 100644 index 00000000..eca16f49 --- /dev/null +++ b/spec/requests/api/v1/fetch_booking_actions/host_unavailable_dates/index_spec.rb @@ -0,0 +1,69 @@ +RSpec.describe "GET /api/v1/bookings", type: :request do + let(:host_profile) { FactoryBot.create(:host_profile) } + let(:host_credentials) { host_profile.user.create_new_auth_token } + let(:host_headers) { { HTTP_ACCEPT: "application/json" }.merge!(host_credentials) } + + let(:random_user) { FactoryBot.create(:user) } + let(:random_user_credentials) { random_user.create_new_auth_token } + let(:random_user_headers) { { HTTP_ACCEPT: "application/json" }.merge!(random_user_credentials) } + + let!(:booking_1) do + FactoryBot.create( + :booking, + host_profile_id: host_profile.id, + status: "accepted", + dates: [1, 2, 3, 2_562_889_600_000] + ) + end + + let!(:booking_2) do + FactoryBot.create( + :booking, + host_profile_id: host_profile.id, + status: "accepted", + dates: [4, 5, 6, 2_462_889_600_000] + ) + end + + let(:unauthenticated_headers) { { HTTP_ACCEPT: "application/json" } } + + describe "successfully" do + describe "when host profile exists" do + before { get "/api/v1/fetch_booking_actions/host_unavailable_dates", headers: host_headers } + + it "with 200 status" do + expect(response.status).to eq 200 + end + + it "with sorted collection of booking dates" do + expect(json_response).to eq [1, 2, 3, 4, 5, 6, 2_462_889_600_000, 2_562_889_600_000] + end + end + + describe "when host profile does not exist" do + before { get "/api/v1/fetch_booking_actions/host_unavailable_dates", headers: random_user_headers } + + it "with 200 status" do + expect(response.status).to eq 200 + end + + it "with empty collection" do + expect(json_response.size).to eq 0 + end + end + end + + describe "unsuccessfully" do + describe "if user is not logged in" do + before { get "/api/v1/fetch_booking_actions/host_unavailable_dates", headers: unauthenticated_headers } + + it "with 401 status" do + expect(response.status).to eq 401 + end + + it "with relevant error" do + expect(json_response["errors"]).to eq ["You need to sign in or sign up before continuing."] + end + end + end +end From 32be7b1bf1523a5793f28c6c1beb126129899766 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Tue, 24 Jan 2023 13:34:26 +0100 Subject: [PATCH 08/32] Creates new endpoint for fetching incoming requests. Adds specs. Passing. --- .../incoming_requests_controller.rb | 10 ++ config/routes.rb | 1 + .../host_unavailable_dates/index_spec.rb | 2 +- .../incoming_requests/index_spec.rb | 93 +++++++++++++++++++ 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb create mode 100644 spec/requests/api/v1/fetch_booking_actions/incoming_requests/index_spec.rb diff --git a/app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb b/app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb new file mode 100644 index 00000000..4f6bccd7 --- /dev/null +++ b/app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb @@ -0,0 +1,10 @@ +class Api::V1::FetchBookingActions::IncomingRequestsController < ApplicationController + before_action :authenticate_api_v1_user!, only: %i[index] + + def index + render json: [], status: 200 and return if current_api_v1_user.host_profile.nil? + + pending_bookings = Booking.where(status: "pending", host_nickname: current_api_v1_user.nickname) + render json: pending_bookings, each_serializer: Bookings::IndexSerializer, status: 200 + end +end diff --git a/config/routes.rb b/config/routes.rb index 03488612..3b42da25 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -24,6 +24,7 @@ resources :incoming_stats, only: [:index] resources :outgoing_stats, only: [:index] resources :host_unavailable_dates, only: [:index] + resources :incoming_requests, only: [:index] end namespace :stripe_actions do diff --git a/spec/requests/api/v1/fetch_booking_actions/host_unavailable_dates/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/host_unavailable_dates/index_spec.rb index eca16f49..f6e7f772 100644 --- a/spec/requests/api/v1/fetch_booking_actions/host_unavailable_dates/index_spec.rb +++ b/spec/requests/api/v1/fetch_booking_actions/host_unavailable_dates/index_spec.rb @@ -1,4 +1,4 @@ -RSpec.describe "GET /api/v1/bookings", type: :request do +RSpec.describe "GET /api/v1/fetch_booking_actions/host_unavailable_dates", type: :request do let(:host_profile) { FactoryBot.create(:host_profile) } let(:host_credentials) { host_profile.user.create_new_auth_token } let(:host_headers) { { HTTP_ACCEPT: "application/json" }.merge!(host_credentials) } diff --git a/spec/requests/api/v1/fetch_booking_actions/incoming_requests/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/incoming_requests/index_spec.rb new file mode 100644 index 00000000..83b34f01 --- /dev/null +++ b/spec/requests/api/v1/fetch_booking_actions/incoming_requests/index_spec.rb @@ -0,0 +1,93 @@ +RSpec.describe "GET /api/v1/fetch_booking_actions/incoming_requests", type: :request do + let(:host_profile) { FactoryBot.create(:host_profile) } + let(:host_credentials) { host_profile.user.create_new_auth_token } + let(:host_headers) { { HTTP_ACCEPT: "application/json" }.merge!(host_credentials) } + + let(:random_user) { FactoryBot.create(:user) } + let(:random_user_credentials) { random_user.create_new_auth_token } + let(:random_user_headers) { { HTTP_ACCEPT: "application/json" }.merge!(random_user_credentials) } + + let!(:booking_1) { FactoryBot.create(:booking, host_nickname: host_profile.user.nickname, status: "pending") } + let!(:booking_2) { FactoryBot.create(:booking, host_nickname: host_profile.user.nickname, status: "pending") } + + let(:unauthenticated_headers) { { HTTP_ACCEPT: "application/json" } } + + describe "successfully" do + describe "when host profile exists" do + before { get "/api/v1/fetch_booking_actions/incoming_requests", headers: host_headers } + + it "with 200 status" do + expect(response.status).to eq 200 + end + + it "with correct amount of bookings" do + expect(json_response.size).to eq 2 + end + + it "with correct number of keys" do + expect(json_response.first.size).to eq 22 + end + + it "with correct names of keys" do + expect(json_response.first).to include( + "id", + "number_of_cats", + "dates", + "status", + "host_id", + "host_profile_id", + "host_profile_score", + "host_location", + "host_nickname", + "message", + "price_total", + "host_message", + "host_avatar", + "host_description", + "host_full_address", + "host_real_lat", + "host_real_long", + "created_at", + "updated_at", + "user_id", + "review_id", + "user" + ) + end + + it "with correct number of keys for user" do + expect(json_response.first["user"].size).to eq 4 + end + + it "with correct names of keys for user" do + expect(json_response.first["user"]).to include("nickname", "location", "id", "profile_avatar") + end + end + + describe "when host profile does not exist" do + before { get "/api/v1/fetch_booking_actions/incoming_requests", headers: random_user_headers } + + it "with 200 status" do + expect(response.status).to eq 200 + end + + it "with empty collection as response" do + expect(json_response.size).to eq 0 + end + end + end + + describe "unsuccessfully" do + describe "if user is not logged in" do + before { get "/api/v1/fetch_booking_actions/incoming_requests", headers: unauthenticated_headers } + + it "with 401 status" do + expect(response.status).to eq 401 + end + + it "with relevant error" do + expect(json_response["errors"]).to eq ["You need to sign in or sign up before continuing."] + end + end + end +end From 6b43101cc47ea654ec4ae83bc1f55617549c6cf0 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Tue, 24 Jan 2023 14:43:44 +0100 Subject: [PATCH 09/32] Creates new endpoint for incoming upcoming bookings. Adds new specs. Passing. --- .../incoming_upcoming_controller.rb | 12 ++ config/routes.rb | 1 + .../incoming_upcoming/index_spec.rb | 107 ++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb create mode 100644 spec/requests/api/v1/fetch_booking_actions/incoming_upcoming/index_spec.rb diff --git a/app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb b/app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb new file mode 100644 index 00000000..7734651c --- /dev/null +++ b/app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb @@ -0,0 +1,12 @@ +class Api::V1::FetchBookingActions::IncomingUpcomingController < ApplicationController + before_action :authenticate_api_v1_user!, only: %i[index] + + def index + render json: [], status: 200 and return if current_api_v1_user.host_profile.nil? + + accepted_bookings = Booking.where(status: "accepted", host_nickname: current_api_v1_user.nickname) + upcoming_bookings = accepted_bookings.select { |booking| booking.dates.last >= DateService.get_js_epoch } + + render json: upcoming_bookings, each_serializer: Bookings::IndexSerializer, status: 200 + end +end diff --git a/config/routes.rb b/config/routes.rb index 3b42da25..cc89e675 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -25,6 +25,7 @@ resources :outgoing_stats, only: [:index] resources :host_unavailable_dates, only: [:index] resources :incoming_requests, only: [:index] + resources :incoming_upcoming, only: [:index] end namespace :stripe_actions do diff --git a/spec/requests/api/v1/fetch_booking_actions/incoming_upcoming/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/incoming_upcoming/index_spec.rb new file mode 100644 index 00000000..31be2087 --- /dev/null +++ b/spec/requests/api/v1/fetch_booking_actions/incoming_upcoming/index_spec.rb @@ -0,0 +1,107 @@ +RSpec.describe "GET /api/v1/fetch_booking_actions/incoming_upcoming", type: :request do + let(:host_profile) { FactoryBot.create(:host_profile) } + let(:host_credentials) { host_profile.user.create_new_auth_token } + let(:host_headers) { { HTTP_ACCEPT: "application/json" }.merge!(host_credentials) } + + let(:random_user) { FactoryBot.create(:user) } + let(:random_user_credentials) { random_user.create_new_auth_token } + let(:random_user_headers) { { HTTP_ACCEPT: "application/json" }.merge!(random_user_credentials) } + + let!(:booking_no_appear) do + FactoryBot.create(:booking, host_nickname: host_profile.user.nickname, status: "accepted", dates: [1, 2, 3]) + end + + let!(:booking_to_appear) do + FactoryBot.create( + :booking, + host_nickname: host_profile.user.nickname, + status: "accepted", + dates: [4, 2_562_889_600_000] + ) + end + + let(:unauthenticated_headers) { { HTTP_ACCEPT: "application/json" } } + + describe "successfully" do + describe "when host profile exists" do + before { get "/api/v1/fetch_booking_actions/incoming_upcoming", headers: host_headers } + + it "with 200 status" do + expect(response.status).to eq 200 + end + + it "with correct amount of bookings" do + expect(json_response.size).to eq 1 + end + + it "with correct booking" do + expect(json_response.first["id"]).to eq booking_to_appear.id + end + + it "with correct number of keys" do + expect(json_response.first.size).to eq 22 + end + + it "with correct names of keys" do + expect(json_response.first).to include( + "id", + "number_of_cats", + "dates", + "status", + "host_id", + "host_profile_id", + "host_profile_score", + "host_location", + "host_nickname", + "message", + "price_total", + "host_message", + "host_avatar", + "host_description", + "host_full_address", + "host_real_lat", + "host_real_long", + "created_at", + "updated_at", + "user_id", + "review_id", + "user" + ) + end + + it "with correct number of keys for user" do + expect(json_response.first["user"].size).to eq 4 + end + + it "with correct names of keys for user" do + expect(json_response.first["user"]).to include("nickname", "location", "id", "profile_avatar") + end + end + + describe "when host profile does not exist" do + before { get "/api/v1/fetch_booking_actions/incoming_upcoming", headers: random_user_headers } + + it "with 200 status" do + expect(response.status).to eq 200 + end + + it "with empty collection as response" do + expect(json_response.size).to eq 0 + end + end + end + + describe "unsuccessfully" do + describe "if user is not logged in" do + before { get "/api/v1/fetch_booking_actions/incoming_upcoming", headers: unauthenticated_headers } + + it "with 401 status" do + expect(response.status).to eq 401 + end + + it "with relevant error" do + expect(json_response["errors"]).to eq ["You need to sign in or sign up before continuing."] + end + end + end +end From 188c3bb7bf830f17c3c76df26cf04dfee94373d8 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Tue, 24 Jan 2023 15:16:02 +0100 Subject: [PATCH 10/32] Creates new endpoint for incoming history bookings. Adds specs. Passing. --- .../incoming_history_controller.rb | 14 +++ config/routes.rb | 1 + .../incoming_history/index_spec.rb | 110 ++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb create mode 100644 spec/requests/api/v1/fetch_booking_actions/incoming_history/index_spec.rb diff --git a/app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb b/app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb new file mode 100644 index 00000000..1f07b595 --- /dev/null +++ b/app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb @@ -0,0 +1,14 @@ +class Api::V1::FetchBookingActions::IncomingHistoryController < ApplicationController + before_action :authenticate_api_v1_user!, only: %i[index] + + def index + render json: [], status: 200 and return if current_api_v1_user.host_profile.nil? + + bookings_declined_canceled = + Booking.where(status: %w[declined canceled], host_nickname: current_api_v1_user.nickname) + accepted_bookings = Booking.where(status: "accepted", host_nickname: current_api_v1_user.nickname) + history_bookings_accepted = accepted_bookings.select { |booking| booking.dates.last < DateService.get_js_epoch } + all_history_bookings = bookings_declined_canceled + history_bookings_accepted + render json: all_history_bookings, each_serializer: Bookings::IndexSerializer, status: 200 + end +end diff --git a/config/routes.rb b/config/routes.rb index cc89e675..0521b45a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -26,6 +26,7 @@ resources :host_unavailable_dates, only: [:index] resources :incoming_requests, only: [:index] resources :incoming_upcoming, only: [:index] + resources :incoming_history, only: [:index] end namespace :stripe_actions do diff --git a/spec/requests/api/v1/fetch_booking_actions/incoming_history/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/incoming_history/index_spec.rb new file mode 100644 index 00000000..03665c20 --- /dev/null +++ b/spec/requests/api/v1/fetch_booking_actions/incoming_history/index_spec.rb @@ -0,0 +1,110 @@ +RSpec.describe "GET /api/v1/fetch_booking_actions/incoming_history", type: :request do + let(:host_profile) { FactoryBot.create(:host_profile) } + let(:host_credentials) { host_profile.user.create_new_auth_token } + let(:host_headers) { { HTTP_ACCEPT: "application/json" }.merge!(host_credentials) } + + let(:random_user) { FactoryBot.create(:user) } + let(:random_user_credentials) { random_user.create_new_auth_token } + let(:random_user_headers) { { HTTP_ACCEPT: "application/json" }.merge!(random_user_credentials) } + + let!(:booking_declined) { FactoryBot.create(:booking, host_nickname: host_profile.user.nickname, status: "declined") } + let!(:booking_canceled) { FactoryBot.create(:booking, host_nickname: host_profile.user.nickname, status: "canceled") } + + let!(:booking_history) do + FactoryBot.create(:booking, host_nickname: host_profile.user.nickname, status: "accepted", dates: [1, 2, 3]) + end + + let!(:booking_future) do + FactoryBot.create( + :booking, + host_nickname: host_profile.user.nickname, + status: "accepted", + dates: [4, 2_562_889_600_000] + ) + end + + let(:unauthenticated_headers) { { HTTP_ACCEPT: "application/json" } } + + describe "successfully" do + describe "when host profile exists" do + before { get "/api/v1/fetch_booking_actions/incoming_history", headers: host_headers } + + it "with 200 status" do + expect(response.status).to eq 200 + end + + it "with correct amount of bookings" do + expect(json_response.size).to eq 3 + end + + it "with future booking not included in the response" do + json_response.each { |response_booking| expect(response_booking["id"]).to_not eq booking_future.id } + end + + it "with correct number of keys" do + expect(json_response.first.size).to eq 22 + end + + it "with correct names of keys" do + expect(json_response.first).to include( + "id", + "number_of_cats", + "dates", + "status", + "host_id", + "host_profile_id", + "host_profile_score", + "host_location", + "host_nickname", + "message", + "price_total", + "host_message", + "host_avatar", + "host_description", + "host_full_address", + "host_real_lat", + "host_real_long", + "created_at", + "updated_at", + "user_id", + "review_id", + "user" + ) + end + + it "with correct number of keys for user" do + expect(json_response.first["user"].size).to eq 4 + end + + it "with correct names of keys for user" do + expect(json_response.first["user"]).to include("nickname", "location", "id", "profile_avatar") + end + end + + describe "when host profile does not exist" do + before { get "/api/v1/fetch_booking_actions/incoming_history", headers: random_user_headers } + + it "with 200 status" do + expect(response.status).to eq 200 + end + + it "with empty collection as response" do + expect(json_response.size).to eq 0 + end + end + end + + describe "unsuccessfully" do + describe "if user is not logged in" do + before { get "/api/v1/fetch_booking_actions/incoming_history", headers: unauthenticated_headers } + + it "with 401 status" do + expect(response.status).to eq 401 + end + + it "with relevant error" do + expect(json_response["errors"]).to eq ["You need to sign in or sign up before continuing."] + end + end + end +end From 226d8ad7c07051b3a908d40f79d28b167681fadc Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Wed, 1 Feb 2023 16:02:10 +0200 Subject: [PATCH 11/32] Creates new endpoint and specs for outgoing requests --- .../outgoing_requests_controller.rb | 8 ++ config/routes.rb | 1 + .../outgoing_requests/index_spec.rb | 75 +++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 app/controllers/api/v1/fetch_booking_actions/outgoing_requests_controller.rb create mode 100644 spec/requests/api/v1/fetch_booking_actions/outgoing_requests/index_spec.rb diff --git a/app/controllers/api/v1/fetch_booking_actions/outgoing_requests_controller.rb b/app/controllers/api/v1/fetch_booking_actions/outgoing_requests_controller.rb new file mode 100644 index 00000000..9d6c42f2 --- /dev/null +++ b/app/controllers/api/v1/fetch_booking_actions/outgoing_requests_controller.rb @@ -0,0 +1,8 @@ +class Api::V1::FetchBookingActions::OutgoingRequestsController < ApplicationController + before_action :authenticate_api_v1_user!, only: %i[index] + + def index + pending_bookings = Booking.where(status: "pending", user_id: current_api_v1_user.id) + render json: pending_bookings, each_serializer: Bookings::IndexSerializer, status: 200 + end +end diff --git a/config/routes.rb b/config/routes.rb index 0521b45a..9f7321b7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -27,6 +27,7 @@ resources :incoming_requests, only: [:index] resources :incoming_upcoming, only: [:index] resources :incoming_history, only: [:index] + resources :outgoing_requests, only: [:index] end namespace :stripe_actions do diff --git a/spec/requests/api/v1/fetch_booking_actions/outgoing_requests/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/outgoing_requests/index_spec.rb new file mode 100644 index 00000000..c05fad32 --- /dev/null +++ b/spec/requests/api/v1/fetch_booking_actions/outgoing_requests/index_spec.rb @@ -0,0 +1,75 @@ +RSpec.describe "GET /api/v1/fetch_booking_actions/outgoing_requests", type: :request do + let(:cat_owner) { FactoryBot.create(:user) } + let(:cat_owner_credentials) { cat_owner.create_new_auth_token } + let(:cat_owner_headers) { { HTTP_ACCEPT: "application/json" }.merge!(cat_owner_credentials) } + + let!(:booking_1) { FactoryBot.create(:booking, user_id: cat_owner.id, status: "pending") } + let!(:booking_2) { FactoryBot.create(:booking, user_id: cat_owner.id, status: "pending") } + + let(:unauthenticated_headers) { { HTTP_ACCEPT: "application/json" } } + + describe "successfully" do + before { get "/api/v1/fetch_booking_actions/outgoing_requests", headers: cat_owner_headers } + + it "with 200 status" do + expect(response.status).to eq 200 + end + + it "with correct amount of bookings" do + expect(json_response.size).to eq 2 + end + + it "with correct number of keys" do + expect(json_response.first.size).to eq 22 + end + + it "with correct names of keys" do + expect(json_response.first).to include( + "id", + "number_of_cats", + "dates", + "status", + "host_id", + "host_profile_id", + "host_profile_score", + "host_location", + "host_nickname", + "message", + "price_total", + "host_message", + "host_avatar", + "host_description", + "host_full_address", + "host_real_lat", + "host_real_long", + "created_at", + "updated_at", + "user_id", + "review_id", + "user" + ) + end + + it "with correct number of keys for user" do + expect(json_response.first["user"].size).to eq 4 + end + + it "with correct names of keys for user" do + expect(json_response.first["user"]).to include("nickname", "location", "id", "profile_avatar") + end + end + + describe "unsuccessfully" do + describe "if user is not logged in" do + before { get "/api/v1/fetch_booking_actions/outgoing_requests", headers: unauthenticated_headers } + + it "with 401 status" do + expect(response.status).to eq 401 + end + + it "with relevant error" do + expect(json_response["errors"]).to eq ["You need to sign in or sign up before continuing."] + end + end + end +end From f40ddc6c7249e7d3cb59e76df822852deba88ea6 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Wed, 1 Feb 2023 16:13:38 +0200 Subject: [PATCH 12/32] Creates new endpoint and specs for outgoing upcoming --- .../outgoing_upcoming_controller.rb | 10 +++ config/routes.rb | 1 + .../outgoing_upcoming/index_spec.rb | 82 +++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 app/controllers/api/v1/fetch_booking_actions/outgoing_upcoming_controller.rb create mode 100644 spec/requests/api/v1/fetch_booking_actions/outgoing_upcoming/index_spec.rb diff --git a/app/controllers/api/v1/fetch_booking_actions/outgoing_upcoming_controller.rb b/app/controllers/api/v1/fetch_booking_actions/outgoing_upcoming_controller.rb new file mode 100644 index 00000000..bf13f796 --- /dev/null +++ b/app/controllers/api/v1/fetch_booking_actions/outgoing_upcoming_controller.rb @@ -0,0 +1,10 @@ +class Api::V1::FetchBookingActions::OutgoingUpcomingController < ApplicationController + before_action :authenticate_api_v1_user!, only: %i[index] + + def index + accepted_bookings = Booking.where(status: "accepted", user_id: current_api_v1_user.id) + upcoming_bookings = accepted_bookings.select { |booking| booking.dates.last >= DateService.get_js_epoch } + + render json: upcoming_bookings, each_serializer: Bookings::IndexSerializer, status: 200 + end +end diff --git a/config/routes.rb b/config/routes.rb index 9f7321b7..02c7a5a1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -28,6 +28,7 @@ resources :incoming_upcoming, only: [:index] resources :incoming_history, only: [:index] resources :outgoing_requests, only: [:index] + resources :outgoing_upcoming, only: [:index] end namespace :stripe_actions do diff --git a/spec/requests/api/v1/fetch_booking_actions/outgoing_upcoming/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/outgoing_upcoming/index_spec.rb new file mode 100644 index 00000000..ff17c620 --- /dev/null +++ b/spec/requests/api/v1/fetch_booking_actions/outgoing_upcoming/index_spec.rb @@ -0,0 +1,82 @@ +RSpec.describe "GET /api/v1/fetch_booking_actions/outgoing_upcoming", type: :request do + let(:cat_owner) { FactoryBot.create(:user) } + let(:cat_owner_credentials) { cat_owner.create_new_auth_token } + let(:cat_owner_headers) { { HTTP_ACCEPT: "application/json" }.merge!(cat_owner_credentials) } + + let!(:booking_no_appear) { FactoryBot.create(:booking, user_id: cat_owner.id, status: "accepted", dates: [1, 2, 3]) } + + let!(:booking_to_appear) do + FactoryBot.create(:booking, user_id: cat_owner.id, status: "accepted", dates: [4, 2_562_889_600_000]) + end + + let(:unauthenticated_headers) { { HTTP_ACCEPT: "application/json" } } + + describe "successfully" do + before { get "/api/v1/fetch_booking_actions/outgoing_upcoming", headers: cat_owner_headers } + + it "with 200 status" do + expect(response.status).to eq 200 + end + + it "with correct amount of bookings" do + expect(json_response.size).to eq 1 + end + + it "with correct booking" do + expect(json_response.first["id"]).to eq booking_to_appear.id + end + + it "with correct number of keys" do + expect(json_response.first.size).to eq 22 + end + + it "with correct names of keys" do + expect(json_response.first).to include( + "id", + "number_of_cats", + "dates", + "status", + "host_id", + "host_profile_id", + "host_profile_score", + "host_location", + "host_nickname", + "message", + "price_total", + "host_message", + "host_avatar", + "host_description", + "host_full_address", + "host_real_lat", + "host_real_long", + "created_at", + "updated_at", + "user_id", + "review_id", + "user" + ) + end + + it "with correct number of keys for user" do + expect(json_response.first["user"].size).to eq 4 + end + + it "with correct names of keys for user" do + expect(json_response.first["user"]).to include("nickname", "location", "id", "profile_avatar") + end + end + + describe "unsuccessfully" do + describe "if user is not logged in" do + before { get "/api/v1/fetch_booking_actions/outgoing_upcoming", headers: unauthenticated_headers } + + it "with 401 status" do + expect(response.status).to eq 401 + end + + it "with relevant error" do + expect(json_response["errors"]).to eq ["You need to sign in or sign up before continuing."] + end + end + end +end From 1aabd2a9293b8f2002ca55d65d72adcc1795e87f Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Wed, 1 Feb 2023 16:28:18 +0200 Subject: [PATCH 13/32] Creates new endpoint and specs for outgoing history --- .../outgoing_history_controller.rb | 11 +++ config/routes.rb | 1 + .../outgoing_history/index_spec.rb | 85 +++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 app/controllers/api/v1/fetch_booking_actions/outgoing_history_controller.rb create mode 100644 spec/requests/api/v1/fetch_booking_actions/outgoing_history/index_spec.rb diff --git a/app/controllers/api/v1/fetch_booking_actions/outgoing_history_controller.rb b/app/controllers/api/v1/fetch_booking_actions/outgoing_history_controller.rb new file mode 100644 index 00000000..624be90a --- /dev/null +++ b/app/controllers/api/v1/fetch_booking_actions/outgoing_history_controller.rb @@ -0,0 +1,11 @@ +class Api::V1::FetchBookingActions::OutgoingHistoryController < ApplicationController + before_action :authenticate_api_v1_user!, only: %i[index] + + def index + bookings_declined_canceled = Booking.where(status: %w[declined canceled], user_id: current_api_v1_user.id) + accepted_bookings = Booking.where(status: "accepted", user_id: current_api_v1_user.id) + history_bookings_accepted = accepted_bookings.select { |booking| booking.dates.last < DateService.get_js_epoch } + all_history_bookings = bookings_declined_canceled + history_bookings_accepted + render json: all_history_bookings, each_serializer: Bookings::IndexSerializer, status: 200 + end +end diff --git a/config/routes.rb b/config/routes.rb index 02c7a5a1..4ff3069d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -29,6 +29,7 @@ resources :incoming_history, only: [:index] resources :outgoing_requests, only: [:index] resources :outgoing_upcoming, only: [:index] + resources :outgoing_history, only: [:index] end namespace :stripe_actions do diff --git a/spec/requests/api/v1/fetch_booking_actions/outgoing_history/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/outgoing_history/index_spec.rb new file mode 100644 index 00000000..74624b0e --- /dev/null +++ b/spec/requests/api/v1/fetch_booking_actions/outgoing_history/index_spec.rb @@ -0,0 +1,85 @@ +RSpec.describe "GET /api/v1/fetch_booking_actions/outgoing_history", type: :request do + let(:cat_owner) { FactoryBot.create(:user) } + let(:cat_owner_credentials) { cat_owner.create_new_auth_token } + let(:cat_owner_headers) { { HTTP_ACCEPT: "application/json" }.merge!(cat_owner_credentials) } + + let!(:booking_declined) { FactoryBot.create(:booking, user_id: cat_owner.id, status: "declined") } + let!(:booking_canceled) { FactoryBot.create(:booking, user_id: cat_owner.id, status: "canceled") } + + let!(:booking_history) { FactoryBot.create(:booking, user_id: cat_owner.id, status: "accepted", dates: [1, 2, 3]) } + + let!(:booking_future) do + FactoryBot.create(:booking, user_id: cat_owner.id, status: "accepted", dates: [4, 2_562_889_600_000]) + end + + let(:unauthenticated_headers) { { HTTP_ACCEPT: "application/json" } } + + describe "successfully" do + before { get "/api/v1/fetch_booking_actions/outgoing_history", headers: cat_owner_headers } + + it "with 200 status" do + expect(response.status).to eq 200 + end + + it "with correct amount of bookings" do + expect(json_response.size).to eq 3 + end + + it "with future booking not included in the response" do + json_response.each { |response_booking| expect(response_booking["id"]).to_not eq booking_future.id } + end + + it "with correct number of keys" do + expect(json_response.first.size).to eq 22 + end + + it "with correct names of keys" do + expect(json_response.first).to include( + "id", + "number_of_cats", + "dates", + "status", + "host_id", + "host_profile_id", + "host_profile_score", + "host_location", + "host_nickname", + "message", + "price_total", + "host_message", + "host_avatar", + "host_description", + "host_full_address", + "host_real_lat", + "host_real_long", + "created_at", + "updated_at", + "user_id", + "review_id", + "user" + ) + end + + it "with correct number of keys for user" do + expect(json_response.first["user"].size).to eq 4 + end + + it "with correct names of keys for user" do + expect(json_response.first["user"]).to include("nickname", "location", "id", "profile_avatar") + end + end + + describe "unsuccessfully" do + describe "if user is not logged in" do + before { get "/api/v1/fetch_booking_actions/outgoing_history", headers: unauthenticated_headers } + + it "with 401 status" do + expect(response.status).to eq 401 + end + + it "with relevant error" do + expect(json_response["errors"]).to eq ["You need to sign in or sign up before continuing."] + end + end + end +end From ca63f5e75dc1052a2d3ac40cac09ca5777e59819 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Wed, 1 Feb 2023 16:44:16 +0200 Subject: [PATCH 14/32] Bookings controller, routes and specs cleanup. All tests passing. --- app/controllers/api/v1/bookings_controller.rb | 78 +----- config/routes.rb | 4 +- spec/requests/api/v1/bookings/index_spec.rb | 227 ------------------ 3 files changed, 3 insertions(+), 306 deletions(-) delete mode 100644 spec/requests/api/v1/bookings/index_spec.rb diff --git a/app/controllers/api/v1/bookings_controller.rb b/app/controllers/api/v1/bookings_controller.rb index 8c59adff..08e31254 100644 --- a/app/controllers/api/v1/bookings_controller.rb +++ b/app/controllers/api/v1/bookings_controller.rb @@ -1,81 +1,5 @@ class Api::V1::BookingsController < ApplicationController - include BookingsConcern - - before_action :authenticate_api_v1_user!, only: %i[index create update] - - def index - case - when params[:stats] == "yes" && params[:host_nickname] == current_api_v1_user.nickname && - params[:user_id].to_i == current_api_v1_user.id - now = DateTime.new(Time.now.year, Time.now.month, Time.now.day, 0, 0, 0, 0) - now_epoch_javascript = (now.to_f * 1000).to_i - incoming_bookings = Booking.where(host_nickname: params[:host_nickname]) - incoming_requests = [] - incoming_upcoming = [] - incoming_history = [] - incoming_unpaid = [] - incoming_bookings.each do |booking| - case - when booking.status == "pending" - incoming_requests.push(booking) - when booking.status == "accepted" && booking.dates.last > now_epoch_javascript - incoming_upcoming.push(booking) - else - incoming_history.push(booking) - end - incoming_unpaid.push(booking) if booking.status == "accepted" && booking.paid == false - end - outgoing_bookings = Booking.where(user_id: params[:user_id]) - outgoing_requests = [] - outgoing_upcoming = [] - outgoing_history = [] - outgoing_unpaid = [] - outgoing_bookings.each do |booking| - case - when booking.status == "pending" - outgoing_requests.push(booking) - when booking.status == "accepted" && booking.dates.last > now_epoch_javascript - outgoing_upcoming.push(booking) - else - outgoing_history.push(booking) - end - outgoing_unpaid.push(booking) if booking.status == "accepted" && booking.paid == false - end - render json: { - stats: { - in_requests: "#{incoming_requests.length}", - in_upcoming: "#{incoming_upcoming.length}", - in_history: "#{incoming_history.length}", - in_unpaid: "#{incoming_unpaid.length}", - out_requests: "#{outgoing_requests.length}", - out_upcoming: "#{outgoing_upcoming.length}", - out_history: "#{outgoing_history.length}", - out_unpaid: "#{outgoing_unpaid.length}" - } - }, - status: 200 - when params[:stats] == "no" && params[:host_nickname] == current_api_v1_user.nickname - if params.has_key?("dates") - bookings = [] - host = User.where(nickname: params[:host_nickname]) - profile = HostProfile.where(user_id: host[0].id) - if profile.length == 1 - render json: find_host_bookings(profile[0].id, 0) - else - render json: bookings - end - else - bookings = Booking.where(host_nickname: params[:host_nickname]) - render json: bookings, each_serializer: Bookings::IndexSerializer - end - when params[:stats] == "no" && params[:user_id].to_i == current_api_v1_user.id - bookings = Booking.where(user_id: params[:user_id]) - render json: bookings, each_serializer: Bookings::IndexSerializer - else - bookings = [] - render json: bookings, each_serializer: Bookings::IndexSerializer - end - end + before_action :authenticate_api_v1_user!, only: %i[create update] def create host = User.find_by(nickname: params[:host_nickname]) diff --git a/config/routes.rb b/config/routes.rb index 4ff3069d..7e903e4f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -12,8 +12,8 @@ resources :users, only: %i[show update] resources :contact_us, only: [:index] resources :host_profiles, only: %i[index show create update] - resources :bookings, only: %i[index create update] - resources :conversations, only: %i[create index show update] + resources :bookings, only: %i[create update] + resources :conversations, only: %i[index show create update] resources :reviews, only: %i[index show create update] namespace :random_reviews do diff --git a/spec/requests/api/v1/bookings/index_spec.rb b/spec/requests/api/v1/bookings/index_spec.rb deleted file mode 100644 index eccfc281..00000000 --- a/spec/requests/api/v1/bookings/index_spec.rb +++ /dev/null @@ -1,227 +0,0 @@ -RSpec.describe "GET /api/v1/bookings", type: :request do - let(:customer) { FactoryBot.create(:user, location: "Athens") } - let(:customer_credentials) { customer.create_new_auth_token } - let(:customer_headers) { { HTTP_ACCEPT: "application/json" }.merge!(customer_credentials) } - - let(:host_profile) { FactoryBot.create(:host_profile) } - let(:host_credentials) { host_profile.user.create_new_auth_token } - let(:host_headers) { { HTTP_ACCEPT: "application/json" }.merge!(host_credentials) } - - let(:random_user) { FactoryBot.create(:user, location: "Stockholm") } - let(:random_user_credentials) { random_user.create_new_auth_token } - let(:random_user_headers) { { HTTP_ACCEPT: "application/json" }.merge!(random_user_credentials) } - - let!(:booking) do - FactoryBot.create( - :booking, - user_id: customer.id, - host_nickname: host_profile.user.nickname, - host_profile_id: host_profile.id, - status: "accepted", - dates: [1, 2, 3, 2_562_889_600_000] - ) - end - - let!(:random_booking) do - FactoryBot.create( - :booking, - host_nickname: host_profile.user.nickname, - host_profile_id: host_profile.id, - status: "accepted", - dates: [4, 5, 6, 2_462_889_600_000] - ) - end - - let(:unauthenticated_headers) { { HTTP_ACCEPT: "application/json" } } - - describe "successfully" do - describe "when stats are asked for" do - describe "and appropriate params are passed" do - describe "with relevant stats for the host" do - before do - get "/api/v1/bookings", - params: { - stats: "yes", - host_nickname: host_profile.user.nickname, - user_id: host_profile.user.id - }, - headers: host_headers - end - - it "is expected to return 200 response status" do - expect(response.status).to eq 200 - end - - it "is expected to return correct booking stats" do - expect( - json_response["stats"].to_json - ).to eq "{\"in_requests\":\"0\",\"in_upcoming\":\"2\",\"in_history\":\"0\",\"in_unpaid\":\"2\",\"out_requests\":\"0\",\"out_upcoming\":\"0\",\"out_history\":\"0\",\"out_unpaid\":\"0\"}" - end - end - - describe "with relevant stats for the customer" do - before do - get "/api/v1/bookings", - params: { - stats: "yes", - host_nickname: customer.nickname, - user_id: customer.id - }, - headers: customer_headers - end - - it "is expected to return 200 response status" do - expect(response.status).to eq 200 - end - - it "is expected to return correct booking stats" do - expect( - json_response["stats"].to_json - ).to eq "{\"in_requests\":\"0\",\"in_upcoming\":\"0\",\"in_history\":\"0\",\"in_unpaid\":\"0\",\"out_requests\":\"0\",\"out_upcoming\":\"1\",\"out_history\":\"0\",\"out_unpaid\":\"1\"}" - end - end - end - - describe "and no params are passed" do - before { get "/api/v1/bookings", headers: customer_headers } - - it "is expected to return empty collection of bookings" do - expect(json_response.count).to eq 0 - end - - it "is expected to return 200 response status" do - expect(response.status).to eq 200 - end - end - end - - describe "when host asks for" do - describe "bookings dates only" do - before do - get "/api/v1/bookings", - params: { - stats: "no", - host_nickname: host_profile.user.nickname, - dates: "only" - }, - headers: host_headers - end - - it "is expected to return 200 response status" do - expect(response.status).to eq 200 - end - - it "is expected to return sorted array of booking dates" do - expect(json_response).to eq [1, 2, 3, 4, 5, 6, 2_462_889_600_000, 2_562_889_600_000] - end - end - - describe "all of their bookings" do - before do - get "/api/v1/bookings", - params: { - stats: "no", - host_nickname: host_profile.user.nickname - }, - headers: host_headers - end - - it "is expected to return 200 response status" do - expect(response.status).to eq 200 - end - - it "is expected to return correct amount of bookings" do - expect(json_response.count).to eq 2 - end - end - end - - describe "when customer asks for all their bookings" do - before { get "/api/v1/bookings", params: { stats: "no", user_id: customer.id }, headers: customer_headers } - - it "with correct number of bookings" do - expect(json_response.count).to eq 1 - end - - it "with correct booking" do - expect(json_response.first["id"]).to eq booking.id - end - - it "with correct number of keys in the response" do - expect(json_response.first.count).to eq 22 - end - - it "with correct keys in the response" do - expect(json_response.first).to include( - "id", - "number_of_cats", - "dates", - "status", - "message", - "host_nickname", - "price_total", - "user_id", - "host_id", - "host_profile_id", - "user", - "host_message", - "host_description", - "host_full_address", - "host_location", - "host_real_lat", - "host_real_long", - "host_avatar", - "review_id", - "host_profile_score" - ) - end - end - end - - describe "unsuccessfully" do - describe "if user is not logged in" do - before { get "/api/v1/bookings/", headers: unauthenticated_headers } - - it "with 401 status" do - expect(response.status).to eq 401 - end - - it "with relevant error" do - expect(json_response["errors"]).to eq ["You need to sign in or sign up before continuing."] - end - end - - describe "if they try to see bookings they are unassociated with" do - describe "for customers" do - before { get "/api/v1/bookings", params: { stats: "no", user_id: customer.id }, headers: random_user_headers } - - it "with 200 status" do - expect(response.status).to eq 200 - end - - it "with an empty array" do - expect(json_response.count).to eq 0 - end - end - - describe "for hosts" do - before do - get "/api/v1/bookings", - params: { - stats: "no", - host_nickname: host_profile.user.nickname - }, - headers: random_user_headers - end - - it "with 200 status" do - expect(response.status).to eq 200 - end - - it "with an empty array" do - expect(json_response.count).to eq 0 - end - end - end - end -end From 32562cbe3ca9e03090aca029912ce2fe29e11f7c Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Fri, 3 Feb 2023 16:32:28 +0200 Subject: [PATCH 15/32] Returns no content when hosto profile does not exist in host_unavailable_dates_controller. Adjusts specs. Passing. --- .../host_unavailable_dates_controller.rb | 2 +- .../host_unavailable_dates/index_spec.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/v1/fetch_booking_actions/host_unavailable_dates_controller.rb b/app/controllers/api/v1/fetch_booking_actions/host_unavailable_dates_controller.rb index 0457186e..3f782726 100644 --- a/app/controllers/api/v1/fetch_booking_actions/host_unavailable_dates_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/host_unavailable_dates_controller.rb @@ -2,7 +2,7 @@ class Api::V1::FetchBookingActions::HostUnavailableDatesController < Application before_action :authenticate_api_v1_user!, only: %i[index] def index - render json: [], status: 200 and return if current_api_v1_user.host_profile.nil? + head :no_content, status: 204 and return if current_api_v1_user.host_profile.nil? render json: BookingService.get_host_unavailable_dates(current_api_v1_user.host_profile.id), status: 200 end diff --git a/spec/requests/api/v1/fetch_booking_actions/host_unavailable_dates/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/host_unavailable_dates/index_spec.rb index f6e7f772..cd978c57 100644 --- a/spec/requests/api/v1/fetch_booking_actions/host_unavailable_dates/index_spec.rb +++ b/spec/requests/api/v1/fetch_booking_actions/host_unavailable_dates/index_spec.rb @@ -43,12 +43,12 @@ describe "when host profile does not exist" do before { get "/api/v1/fetch_booking_actions/host_unavailable_dates", headers: random_user_headers } - it "with 200 status" do - expect(response.status).to eq 200 + it "with 204 status" do + expect(response.status).to eq 204 end - it "with empty collection" do - expect(json_response.size).to eq 0 + it "with empty response body" do + expect(response.body).to eq "" end end end From cf0174bca17df5ca77a8e2a2db8ba99879547783 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Fri, 3 Feb 2023 16:36:05 +0200 Subject: [PATCH 16/32] Returns no content when hosto profile does not exist in incoming_history_controller. Adjusts specs. Passing. --- .../fetch_booking_actions/incoming_history_controller.rb | 2 +- .../fetch_booking_actions/incoming_history/index_spec.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb b/app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb index 1f07b595..8b9689a0 100644 --- a/app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb @@ -2,7 +2,7 @@ class Api::V1::FetchBookingActions::IncomingHistoryController < ApplicationContr before_action :authenticate_api_v1_user!, only: %i[index] def index - render json: [], status: 200 and return if current_api_v1_user.host_profile.nil? + head :no_content, status: 204 and return if current_api_v1_user.host_profile.nil? bookings_declined_canceled = Booking.where(status: %w[declined canceled], host_nickname: current_api_v1_user.nickname) diff --git a/spec/requests/api/v1/fetch_booking_actions/incoming_history/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/incoming_history/index_spec.rb index 03665c20..6bd917dd 100644 --- a/spec/requests/api/v1/fetch_booking_actions/incoming_history/index_spec.rb +++ b/spec/requests/api/v1/fetch_booking_actions/incoming_history/index_spec.rb @@ -84,12 +84,12 @@ describe "when host profile does not exist" do before { get "/api/v1/fetch_booking_actions/incoming_history", headers: random_user_headers } - it "with 200 status" do - expect(response.status).to eq 200 + it "with 204 status" do + expect(response.status).to eq 204 end - it "with empty collection as response" do - expect(json_response.size).to eq 0 + it "with empty response body" do + expect(response.body).to eq "" end end end From 51d21be93c9836d264afd9079fa65d506e7ca6d4 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Fri, 3 Feb 2023 16:38:29 +0200 Subject: [PATCH 17/32] Returns no content when host profile does not exist in incoming_requests_controller. Adjusts specs. Passing. --- .../fetch_booking_actions/incoming_requests_controller.rb | 2 +- .../fetch_booking_actions/incoming_requests/index_spec.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb b/app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb index 4f6bccd7..8e309046 100644 --- a/app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb @@ -2,7 +2,7 @@ class Api::V1::FetchBookingActions::IncomingRequestsController < ApplicationCont before_action :authenticate_api_v1_user!, only: %i[index] def index - render json: [], status: 200 and return if current_api_v1_user.host_profile.nil? + head :no_content, status: 204 and return if current_api_v1_user.host_profile.nil? pending_bookings = Booking.where(status: "pending", host_nickname: current_api_v1_user.nickname) render json: pending_bookings, each_serializer: Bookings::IndexSerializer, status: 200 diff --git a/spec/requests/api/v1/fetch_booking_actions/incoming_requests/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/incoming_requests/index_spec.rb index 83b34f01..c06b5994 100644 --- a/spec/requests/api/v1/fetch_booking_actions/incoming_requests/index_spec.rb +++ b/spec/requests/api/v1/fetch_booking_actions/incoming_requests/index_spec.rb @@ -67,12 +67,12 @@ describe "when host profile does not exist" do before { get "/api/v1/fetch_booking_actions/incoming_requests", headers: random_user_headers } - it "with 200 status" do - expect(response.status).to eq 200 + it "with 204 status" do + expect(response.status).to eq 204 end - it "with empty collection as response" do - expect(json_response.size).to eq 0 + it "with empty response body" do + expect(response.body).to eq "" end end end From 7f5b03f9838aeac87989c1adc477e4ed5e099e92 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Fri, 3 Feb 2023 16:41:36 +0200 Subject: [PATCH 18/32] Returns no content when host profile does not exist in incoming_stats_controller. Adjusts specs. Passing. --- .../v1/fetch_booking_actions/incoming_stats_controller.rb | 2 +- .../v1/fetch_booking_actions/incoming_stats/index_spec.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/v1/fetch_booking_actions/incoming_stats_controller.rb b/app/controllers/api/v1/fetch_booking_actions/incoming_stats_controller.rb index 5691d45e..c6face60 100644 --- a/app/controllers/api/v1/fetch_booking_actions/incoming_stats_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/incoming_stats_controller.rb @@ -2,7 +2,7 @@ class Api::V1::FetchBookingActions::IncomingStatsController < ApplicationControl before_action :authenticate_api_v1_user!, only: %i[index] def index - render json: [], status: 200 and return if current_api_v1_user.host_profile.nil? + head :no_content, status: 204 and return if current_api_v1_user.host_profile.nil? pending_bookings = Booking.where(status: "pending", host_nickname: current_api_v1_user.nickname).size unpaid_bookings = Booking.where(status: "accepted", host_nickname: current_api_v1_user.nickname, paid: false).size diff --git a/spec/requests/api/v1/fetch_booking_actions/incoming_stats/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/incoming_stats/index_spec.rb index f528f9ae..9d4dd0f6 100644 --- a/spec/requests/api/v1/fetch_booking_actions/incoming_stats/index_spec.rb +++ b/spec/requests/api/v1/fetch_booking_actions/incoming_stats/index_spec.rb @@ -63,12 +63,12 @@ describe "when user has no host profile" do before { get "/api/v1/fetch_booking_actions/incoming_stats", headers: random_user_headers } - it "with 200 status" do - expect(response.status).to eq 200 + it "with 204 status" do + expect(response.status).to eq 204 end - it "with empty collection in the response" do - expect(json_response.size).to eq 0 + it "with empty response body" do + expect(response.body).to eq "" end end end From 81154906690f37dd333f2f25bf5b7185f9f298d2 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Fri, 3 Feb 2023 16:44:14 +0200 Subject: [PATCH 19/32] Returns no content when host profile does not exist in incoming_upcoming_controller. Adjusts specs. Passing. --- .../fetch_booking_actions/incoming_upcoming_controller.rb | 2 +- .../fetch_booking_actions/incoming_upcoming/index_spec.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb b/app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb index 7734651c..221465ac 100644 --- a/app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb @@ -2,7 +2,7 @@ class Api::V1::FetchBookingActions::IncomingUpcomingController < ApplicationCont before_action :authenticate_api_v1_user!, only: %i[index] def index - render json: [], status: 200 and return if current_api_v1_user.host_profile.nil? + head :no_content, status: 204 and return if current_api_v1_user.host_profile.nil? accepted_bookings = Booking.where(status: "accepted", host_nickname: current_api_v1_user.nickname) upcoming_bookings = accepted_bookings.select { |booking| booking.dates.last >= DateService.get_js_epoch } diff --git a/spec/requests/api/v1/fetch_booking_actions/incoming_upcoming/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/incoming_upcoming/index_spec.rb index 31be2087..c358cc00 100644 --- a/spec/requests/api/v1/fetch_booking_actions/incoming_upcoming/index_spec.rb +++ b/spec/requests/api/v1/fetch_booking_actions/incoming_upcoming/index_spec.rb @@ -81,12 +81,12 @@ describe "when host profile does not exist" do before { get "/api/v1/fetch_booking_actions/incoming_upcoming", headers: random_user_headers } - it "with 200 status" do - expect(response.status).to eq 200 + it "with 204 status" do + expect(response.status).to eq 204 end - it "with empty collection as response" do - expect(json_response.size).to eq 0 + it "with empty response body" do + expect(response.body).to eq "" end end end From 26466898f0bbe53c31c0bd9fff59f6a0572c2bf1 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Sat, 4 Feb 2023 17:00:02 +0200 Subject: [PATCH 20/32] Sorts requests. Adds relevant specs. All passing. --- .../incoming_requests_controller.rb | 6 ++++- .../outgoing_requests_controller.rb | 3 ++- .../incoming_requests/index_spec.rb | 23 +++++++++++++++++-- .../outgoing_requests/index_spec.rb | 23 +++++++++++++++++-- 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb b/app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb index 8e309046..d5b523e0 100644 --- a/app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb @@ -4,7 +4,11 @@ class Api::V1::FetchBookingActions::IncomingRequestsController < ApplicationCont def index head :no_content, status: 204 and return if current_api_v1_user.host_profile.nil? - pending_bookings = Booking.where(status: "pending", host_nickname: current_api_v1_user.nickname) + pending_bookings = + Booking + .where(status: "pending", host_nickname: current_api_v1_user.nickname) + .sort_by { |booking| booking.created_at } + .reverse render json: pending_bookings, each_serializer: Bookings::IndexSerializer, status: 200 end end diff --git a/app/controllers/api/v1/fetch_booking_actions/outgoing_requests_controller.rb b/app/controllers/api/v1/fetch_booking_actions/outgoing_requests_controller.rb index 9d6c42f2..b54f2f0a 100644 --- a/app/controllers/api/v1/fetch_booking_actions/outgoing_requests_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/outgoing_requests_controller.rb @@ -2,7 +2,8 @@ class Api::V1::FetchBookingActions::OutgoingRequestsController < ApplicationCont before_action :authenticate_api_v1_user!, only: %i[index] def index - pending_bookings = Booking.where(status: "pending", user_id: current_api_v1_user.id) + pending_bookings = + Booking.where(status: "pending", user_id: current_api_v1_user.id).sort_by { |booking| booking.created_at }.reverse render json: pending_bookings, each_serializer: Bookings::IndexSerializer, status: 200 end end diff --git a/spec/requests/api/v1/fetch_booking_actions/incoming_requests/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/incoming_requests/index_spec.rb index c06b5994..7f055f86 100644 --- a/spec/requests/api/v1/fetch_booking_actions/incoming_requests/index_spec.rb +++ b/spec/requests/api/v1/fetch_booking_actions/incoming_requests/index_spec.rb @@ -7,8 +7,23 @@ let(:random_user_credentials) { random_user.create_new_auth_token } let(:random_user_headers) { { HTTP_ACCEPT: "application/json" }.merge!(random_user_credentials) } - let!(:booking_1) { FactoryBot.create(:booking, host_nickname: host_profile.user.nickname, status: "pending") } - let!(:booking_2) { FactoryBot.create(:booking, host_nickname: host_profile.user.nickname, status: "pending") } + let!(:booking_1) do + FactoryBot.create( + :booking, + host_nickname: host_profile.user.nickname, + status: "pending", + created_at: "Thu, 01 Jan 2023 00:03:00 UTC +00:00" + ) + end + + let!(:booking_2) do + FactoryBot.create( + :booking, + host_nickname: host_profile.user.nickname, + status: "pending", + created_at: "Fri, 02 Jan 2023 00:03:00 UTC +00:00" + ) + end let(:unauthenticated_headers) { { HTTP_ACCEPT: "application/json" } } @@ -24,6 +39,10 @@ expect(json_response.size).to eq 2 end + it "with correct order of bookings" do + expect(json_response.first["id"]).to eq booking_2.id + end + it "with correct number of keys" do expect(json_response.first.size).to eq 22 end diff --git a/spec/requests/api/v1/fetch_booking_actions/outgoing_requests/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/outgoing_requests/index_spec.rb index c05fad32..ad447e0c 100644 --- a/spec/requests/api/v1/fetch_booking_actions/outgoing_requests/index_spec.rb +++ b/spec/requests/api/v1/fetch_booking_actions/outgoing_requests/index_spec.rb @@ -3,8 +3,23 @@ let(:cat_owner_credentials) { cat_owner.create_new_auth_token } let(:cat_owner_headers) { { HTTP_ACCEPT: "application/json" }.merge!(cat_owner_credentials) } - let!(:booking_1) { FactoryBot.create(:booking, user_id: cat_owner.id, status: "pending") } - let!(:booking_2) { FactoryBot.create(:booking, user_id: cat_owner.id, status: "pending") } + let!(:booking_1) do + FactoryBot.create( + :booking, + user_id: cat_owner.id, + status: "pending", + created_at: "Thu, 01 Jan 2023 00:03:00 UTC +00:00" + ) + end + + let!(:booking_2) do + FactoryBot.create( + :booking, + user_id: cat_owner.id, + status: "pending", + created_at: "Fri, 02 Jan 2023 00:03:00 UTC +00:00" + ) + end let(:unauthenticated_headers) { { HTTP_ACCEPT: "application/json" } } @@ -19,6 +34,10 @@ expect(json_response.size).to eq 2 end + it "with correct order of bookings" do + expect(json_response.first["id"]).to eq booking_2.id + end + it "with correct number of keys" do expect(json_response.first.size).to eq 22 end From fd7fbee305998ae3295f405be5decae79a5f8610 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Sat, 4 Feb 2023 17:17:22 +0200 Subject: [PATCH 21/32] Sorts upcoming. Adds relevant specs. All passing. --- .../incoming_upcoming_controller.rb | 5 +++- .../outgoing_upcoming_controller.rb | 5 +++- .../incoming_upcoming/index_spec.rb | 23 +++++++++++++++---- .../outgoing_upcoming/index_spec.rb | 18 +++++++++++---- 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb b/app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb index 221465ac..2062e8f1 100644 --- a/app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb @@ -5,7 +5,10 @@ def index head :no_content, status: 204 and return if current_api_v1_user.host_profile.nil? accepted_bookings = Booking.where(status: "accepted", host_nickname: current_api_v1_user.nickname) - upcoming_bookings = accepted_bookings.select { |booking| booking.dates.last >= DateService.get_js_epoch } + upcoming_bookings = + accepted_bookings + .select { |booking| booking.dates.last >= DateService.get_js_epoch } + .sort_by { |booking| booking.dates.first } render json: upcoming_bookings, each_serializer: Bookings::IndexSerializer, status: 200 end diff --git a/app/controllers/api/v1/fetch_booking_actions/outgoing_upcoming_controller.rb b/app/controllers/api/v1/fetch_booking_actions/outgoing_upcoming_controller.rb index bf13f796..40d80b70 100644 --- a/app/controllers/api/v1/fetch_booking_actions/outgoing_upcoming_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/outgoing_upcoming_controller.rb @@ -3,7 +3,10 @@ class Api::V1::FetchBookingActions::OutgoingUpcomingController < ApplicationCont def index accepted_bookings = Booking.where(status: "accepted", user_id: current_api_v1_user.id) - upcoming_bookings = accepted_bookings.select { |booking| booking.dates.last >= DateService.get_js_epoch } + upcoming_bookings = + accepted_bookings + .select { |booking| booking.dates.last >= DateService.get_js_epoch } + .sort_by { |booking| booking.dates.first } render json: upcoming_bookings, each_serializer: Bookings::IndexSerializer, status: 200 end diff --git a/spec/requests/api/v1/fetch_booking_actions/incoming_upcoming/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/incoming_upcoming/index_spec.rb index c358cc00..847115ec 100644 --- a/spec/requests/api/v1/fetch_booking_actions/incoming_upcoming/index_spec.rb +++ b/spec/requests/api/v1/fetch_booking_actions/incoming_upcoming/index_spec.rb @@ -11,12 +11,21 @@ FactoryBot.create(:booking, host_nickname: host_profile.user.nickname, status: "accepted", dates: [1, 2, 3]) end - let!(:booking_to_appear) do + let!(:booking_to_appear_1) do FactoryBot.create( :booking, host_nickname: host_profile.user.nickname, status: "accepted", - dates: [4, 2_562_889_600_000] + dates: [5, 2_562_889_600_000] + ) + end + + let!(:booking_to_appear_2) do + FactoryBot.create( + :booking, + host_nickname: host_profile.user.nickname, + status: "accepted", + dates: [4, 2_662_889_600_000] ) end @@ -31,11 +40,15 @@ end it "with correct amount of bookings" do - expect(json_response.size).to eq 1 + expect(json_response.size).to eq 2 + end + + it "with correct order of bookings - first" do + expect(json_response.first["id"]).to eq booking_to_appear_2.id end - it "with correct booking" do - expect(json_response.first["id"]).to eq booking_to_appear.id + it "with correct order of bookings - last" do + expect(json_response.last["id"]).to eq booking_to_appear_1.id end it "with correct number of keys" do diff --git a/spec/requests/api/v1/fetch_booking_actions/outgoing_upcoming/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/outgoing_upcoming/index_spec.rb index ff17c620..7994ced5 100644 --- a/spec/requests/api/v1/fetch_booking_actions/outgoing_upcoming/index_spec.rb +++ b/spec/requests/api/v1/fetch_booking_actions/outgoing_upcoming/index_spec.rb @@ -5,8 +5,12 @@ let!(:booking_no_appear) { FactoryBot.create(:booking, user_id: cat_owner.id, status: "accepted", dates: [1, 2, 3]) } - let!(:booking_to_appear) do - FactoryBot.create(:booking, user_id: cat_owner.id, status: "accepted", dates: [4, 2_562_889_600_000]) + let!(:booking_to_appear_1) do + FactoryBot.create(:booking, user_id: cat_owner.id, status: "accepted", dates: [5, 2_562_889_600_000]) + end + + let!(:booking_to_appear_2) do + FactoryBot.create(:booking, user_id: cat_owner.id, status: "accepted", dates: [4, 2_662_889_600_000]) end let(:unauthenticated_headers) { { HTTP_ACCEPT: "application/json" } } @@ -19,11 +23,15 @@ end it "with correct amount of bookings" do - expect(json_response.size).to eq 1 + expect(json_response.size).to eq 2 + end + + it "with correct order of bookings - first" do + expect(json_response.first["id"]).to eq booking_to_appear_2.id end - it "with correct booking" do - expect(json_response.first["id"]).to eq booking_to_appear.id + it "with correct order of bookings - last" do + expect(json_response.last["id"]).to eq booking_to_appear_1.id end it "with correct number of keys" do From 9343c8588120198686ef5d3c2db2ba0a13daade0 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Sat, 4 Feb 2023 17:35:13 +0200 Subject: [PATCH 22/32] Sorts history. Adds relevant specs. All passing. --- .../incoming_history_controller.rb | 3 ++- .../outgoing_history_controller.rb | 3 ++- .../incoming_history/index_spec.rb | 21 +++++++++++++++---- .../outgoing_history/index_spec.rb | 17 ++++++++++----- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb b/app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb index 8b9689a0..f9b4e92b 100644 --- a/app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb @@ -8,7 +8,8 @@ def index Booking.where(status: %w[declined canceled], host_nickname: current_api_v1_user.nickname) accepted_bookings = Booking.where(status: "accepted", host_nickname: current_api_v1_user.nickname) history_bookings_accepted = accepted_bookings.select { |booking| booking.dates.last < DateService.get_js_epoch } - all_history_bookings = bookings_declined_canceled + history_bookings_accepted + all_history_bookings = + (bookings_declined_canceled + history_bookings_accepted).sort_by { |booking| booking.dates.first }.reverse render json: all_history_bookings, each_serializer: Bookings::IndexSerializer, status: 200 end end diff --git a/app/controllers/api/v1/fetch_booking_actions/outgoing_history_controller.rb b/app/controllers/api/v1/fetch_booking_actions/outgoing_history_controller.rb index 624be90a..d85a958d 100644 --- a/app/controllers/api/v1/fetch_booking_actions/outgoing_history_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/outgoing_history_controller.rb @@ -5,7 +5,8 @@ def index bookings_declined_canceled = Booking.where(status: %w[declined canceled], user_id: current_api_v1_user.id) accepted_bookings = Booking.where(status: "accepted", user_id: current_api_v1_user.id) history_bookings_accepted = accepted_bookings.select { |booking| booking.dates.last < DateService.get_js_epoch } - all_history_bookings = bookings_declined_canceled + history_bookings_accepted + all_history_bookings = + (bookings_declined_canceled + history_bookings_accepted).sort_by { |booking| booking.dates.first }.reverse render json: all_history_bookings, each_serializer: Bookings::IndexSerializer, status: 200 end end diff --git a/spec/requests/api/v1/fetch_booking_actions/incoming_history/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/incoming_history/index_spec.rb index 6bd917dd..42159c19 100644 --- a/spec/requests/api/v1/fetch_booking_actions/incoming_history/index_spec.rb +++ b/spec/requests/api/v1/fetch_booking_actions/incoming_history/index_spec.rb @@ -7,11 +7,16 @@ let(:random_user_credentials) { random_user.create_new_auth_token } let(:random_user_headers) { { HTTP_ACCEPT: "application/json" }.merge!(random_user_credentials) } - let!(:booking_declined) { FactoryBot.create(:booking, host_nickname: host_profile.user.nickname, status: "declined") } - let!(:booking_canceled) { FactoryBot.create(:booking, host_nickname: host_profile.user.nickname, status: "canceled") } + let!(:booking_declined) do + FactoryBot.create(:booking, host_nickname: host_profile.user.nickname, status: "declined", dates: [1, 2, 3]) + end + + let!(:booking_canceled) do + FactoryBot.create(:booking, host_nickname: host_profile.user.nickname, status: "canceled", dates: [4, 5, 6]) + end let!(:booking_history) do - FactoryBot.create(:booking, host_nickname: host_profile.user.nickname, status: "accepted", dates: [1, 2, 3]) + FactoryBot.create(:booking, host_nickname: host_profile.user.nickname, status: "accepted", dates: [7, 8, 9]) end let!(:booking_future) do @@ -19,7 +24,7 @@ :booking, host_nickname: host_profile.user.nickname, status: "accepted", - dates: [4, 2_562_889_600_000] + dates: [10, 2_562_889_600_000] ) end @@ -37,6 +42,14 @@ expect(json_response.size).to eq 3 end + it "with correct order of bookings - first" do + expect(json_response.first["id"]).to eq booking_history.id + end + + it "with correct order of bookings - last" do + expect(json_response.last["id"]).to eq booking_declined.id + end + it "with future booking not included in the response" do json_response.each { |response_booking| expect(response_booking["id"]).to_not eq booking_future.id } end diff --git a/spec/requests/api/v1/fetch_booking_actions/outgoing_history/index_spec.rb b/spec/requests/api/v1/fetch_booking_actions/outgoing_history/index_spec.rb index 74624b0e..d9bc485b 100644 --- a/spec/requests/api/v1/fetch_booking_actions/outgoing_history/index_spec.rb +++ b/spec/requests/api/v1/fetch_booking_actions/outgoing_history/index_spec.rb @@ -3,13 +3,12 @@ let(:cat_owner_credentials) { cat_owner.create_new_auth_token } let(:cat_owner_headers) { { HTTP_ACCEPT: "application/json" }.merge!(cat_owner_credentials) } - let!(:booking_declined) { FactoryBot.create(:booking, user_id: cat_owner.id, status: "declined") } - let!(:booking_canceled) { FactoryBot.create(:booking, user_id: cat_owner.id, status: "canceled") } - - let!(:booking_history) { FactoryBot.create(:booking, user_id: cat_owner.id, status: "accepted", dates: [1, 2, 3]) } + let!(:booking_declined) { FactoryBot.create(:booking, user_id: cat_owner.id, status: "declined", dates: [1, 2, 3]) } + let!(:booking_canceled) { FactoryBot.create(:booking, user_id: cat_owner.id, status: "canceled", dates: [4, 5, 6]) } + let!(:booking_history) { FactoryBot.create(:booking, user_id: cat_owner.id, status: "accepted", dates: [7, 8, 9]) } let!(:booking_future) do - FactoryBot.create(:booking, user_id: cat_owner.id, status: "accepted", dates: [4, 2_562_889_600_000]) + FactoryBot.create(:booking, user_id: cat_owner.id, status: "accepted", dates: [10, 2_562_889_600_000]) end let(:unauthenticated_headers) { { HTTP_ACCEPT: "application/json" } } @@ -25,6 +24,14 @@ expect(json_response.size).to eq 3 end + it "with correct order of bookings - first" do + expect(json_response.first["id"]).to eq booking_history.id + end + + it "with correct order of bookings - last" do + expect(json_response.last["id"]).to eq booking_declined.id + end + it "with future booking not included in the response" do json_response.each { |response_booking| expect(response_booking["id"]).to_not eq booking_future.id } end From 87fbd6c6efd19ac2fa41caea0c12a29d38fe10dc Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Sat, 4 Feb 2023 17:53:34 +0200 Subject: [PATCH 23/32] Extracts logic of history in model method. Relevant specs passing. --- .../incoming_history_controller.rb | 10 +++------- .../outgoing_history_controller.rb | 9 +++------ app/models/booking.rb | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb b/app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb index f9b4e92b..55197974 100644 --- a/app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/incoming_history_controller.rb @@ -4,12 +4,8 @@ class Api::V1::FetchBookingActions::IncomingHistoryController < ApplicationContr def index head :no_content, status: 204 and return if current_api_v1_user.host_profile.nil? - bookings_declined_canceled = - Booking.where(status: %w[declined canceled], host_nickname: current_api_v1_user.nickname) - accepted_bookings = Booking.where(status: "accepted", host_nickname: current_api_v1_user.nickname) - history_bookings_accepted = accepted_bookings.select { |booking| booking.dates.last < DateService.get_js_epoch } - all_history_bookings = - (bookings_declined_canceled + history_bookings_accepted).sort_by { |booking| booking.dates.first }.reverse - render json: all_history_bookings, each_serializer: Bookings::IndexSerializer, status: 200 + render json: Booking.get_history_bookings_sorted(current_api_v1_user.nickname, nil), + each_serializer: Bookings::IndexSerializer, + status: 200 end end diff --git a/app/controllers/api/v1/fetch_booking_actions/outgoing_history_controller.rb b/app/controllers/api/v1/fetch_booking_actions/outgoing_history_controller.rb index d85a958d..f118dc45 100644 --- a/app/controllers/api/v1/fetch_booking_actions/outgoing_history_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/outgoing_history_controller.rb @@ -2,11 +2,8 @@ class Api::V1::FetchBookingActions::OutgoingHistoryController < ApplicationContr before_action :authenticate_api_v1_user!, only: %i[index] def index - bookings_declined_canceled = Booking.where(status: %w[declined canceled], user_id: current_api_v1_user.id) - accepted_bookings = Booking.where(status: "accepted", user_id: current_api_v1_user.id) - history_bookings_accepted = accepted_bookings.select { |booking| booking.dates.last < DateService.get_js_epoch } - all_history_bookings = - (bookings_declined_canceled + history_bookings_accepted).sort_by { |booking| booking.dates.first }.reverse - render json: all_history_bookings, each_serializer: Bookings::IndexSerializer, status: 200 + render json: Booking.get_history_bookings_sorted(nil, current_api_v1_user.id), + each_serializer: Bookings::IndexSerializer, + status: 200 end end diff --git a/app/models/booking.rb b/app/models/booking.rb index b9c2366c..ee05a696 100644 --- a/app/models/booking.rb +++ b/app/models/booking.rb @@ -25,4 +25,22 @@ def self.cached_by_host_profile_id(host_profile_id) Rails.cache.fetch("bookings_with_host_profile_id_#{host_profile_id}") end end + + def self.get_history_bookings_sorted(host_nickname, user_id) + if !user_id.nil? + bookings_declined_canceled = Booking.where(status: %w[declined canceled], user_id: user_id) + accepted_bookings = Booking.where(status: "accepted", user_id: user_id) + history_bookings_accepted = accepted_bookings.select { |booking| booking.dates.last < DateService.get_js_epoch } + all_history_bookings = + (bookings_declined_canceled + history_bookings_accepted).sort_by { |booking| booking.dates.first }.reverse + return all_history_bookings + end + + bookings_declined_canceled = Booking.where(status: %w[declined canceled], host_nickname: host_nickname) + accepted_bookings = Booking.where(status: "accepted", host_nickname: host_nickname) + history_bookings_accepted = accepted_bookings.select { |booking| booking.dates.last < DateService.get_js_epoch } + all_history_bookings = + (bookings_declined_canceled + history_bookings_accepted).sort_by { |booking| booking.dates.first }.reverse + return all_history_bookings + end end From 6fdfc3a224889001cc54da46bcb3274da4ae5132 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Sat, 4 Feb 2023 18:20:45 +0200 Subject: [PATCH 24/32] Refactors logic of history in model method. Relevant specs passing. --- app/models/booking.rb | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/app/models/booking.rb b/app/models/booking.rb index ee05a696..0f5849c6 100644 --- a/app/models/booking.rb +++ b/app/models/booking.rb @@ -27,17 +27,22 @@ def self.cached_by_host_profile_id(host_profile_id) end def self.get_history_bookings_sorted(host_nickname, user_id) - if !user_id.nil? - bookings_declined_canceled = Booking.where(status: %w[declined canceled], user_id: user_id) - accepted_bookings = Booking.where(status: "accepted", user_id: user_id) - history_bookings_accepted = accepted_bookings.select { |booking| booking.dates.last < DateService.get_js_epoch } - all_history_bookings = - (bookings_declined_canceled + history_bookings_accepted).sort_by { |booking| booking.dates.first }.reverse - return all_history_bookings - end - - bookings_declined_canceled = Booking.where(status: %w[declined canceled], host_nickname: host_nickname) - accepted_bookings = Booking.where(status: "accepted", host_nickname: host_nickname) + bookings_declined_canceled = + ( + if user_id.nil? + Booking.where(status: %w[declined canceled], host_nickname: host_nickname) + else + Booking.where(status: %w[declined canceled], user_id: user_id) + end + ) + accepted_bookings = + ( + if user_id.nil? + Booking.where(status: "accepted", host_nickname: host_nickname) + else + Booking.where(status: "accepted", user_id: user_id) + end + ) history_bookings_accepted = accepted_bookings.select { |booking| booking.dates.last < DateService.get_js_epoch } all_history_bookings = (bookings_declined_canceled + history_bookings_accepted).sort_by { |booking| booking.dates.first }.reverse From 62e581999574bb767b691cf33629026f1f0f0fec Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Sat, 4 Feb 2023 18:34:15 +0200 Subject: [PATCH 25/32] Extracts logic of requests in model method. Relevant specs passing. --- .../incoming_requests_controller.rb | 9 +++------ .../outgoing_requests_controller.rb | 6 +++--- app/models/booking.rb | 12 ++++++++++++ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb b/app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb index d5b523e0..3d731d6b 100644 --- a/app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/incoming_requests_controller.rb @@ -4,11 +4,8 @@ class Api::V1::FetchBookingActions::IncomingRequestsController < ApplicationCont def index head :no_content, status: 204 and return if current_api_v1_user.host_profile.nil? - pending_bookings = - Booking - .where(status: "pending", host_nickname: current_api_v1_user.nickname) - .sort_by { |booking| booking.created_at } - .reverse - render json: pending_bookings, each_serializer: Bookings::IndexSerializer, status: 200 + render json: Booking.get_request_bookings_sorted(current_api_v1_user.nickname, nil), + each_serializer: Bookings::IndexSerializer, + status: 200 end end diff --git a/app/controllers/api/v1/fetch_booking_actions/outgoing_requests_controller.rb b/app/controllers/api/v1/fetch_booking_actions/outgoing_requests_controller.rb index b54f2f0a..35b085fe 100644 --- a/app/controllers/api/v1/fetch_booking_actions/outgoing_requests_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/outgoing_requests_controller.rb @@ -2,8 +2,8 @@ class Api::V1::FetchBookingActions::OutgoingRequestsController < ApplicationCont before_action :authenticate_api_v1_user!, only: %i[index] def index - pending_bookings = - Booking.where(status: "pending", user_id: current_api_v1_user.id).sort_by { |booking| booking.created_at }.reverse - render json: pending_bookings, each_serializer: Bookings::IndexSerializer, status: 200 + render json: Booking.get_request_bookings_sorted(nil, current_api_v1_user.id), + each_serializer: Bookings::IndexSerializer, + status: 200 end end diff --git a/app/models/booking.rb b/app/models/booking.rb index 0f5849c6..ca10e3f8 100644 --- a/app/models/booking.rb +++ b/app/models/booking.rb @@ -48,4 +48,16 @@ def self.get_history_bookings_sorted(host_nickname, user_id) (bookings_declined_canceled + history_bookings_accepted).sort_by { |booking| booking.dates.first }.reverse return all_history_bookings end + + def self.get_request_bookings_sorted(host_nickname, user_id) + pending_bookings = + ( + if user_id.nil? + Booking.where(status: "pending", host_nickname: host_nickname) + else + Booking.where(status: "pending", user_id: user_id) + end + ) + return pending_bookings.sort_by { |booking| booking.created_at }.reverse + end end From 448b192a32017bba6fe4c65d7430e0bb1dc3b39f Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Sat, 4 Feb 2023 18:42:36 +0200 Subject: [PATCH 26/32] Extracts logic of upcoming in model method. Relevant specs passing. --- .../incoming_upcoming_controller.rb | 10 +++------- .../outgoing_upcoming_controller.rb | 10 +++------- app/models/booking.rb | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb b/app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb index 2062e8f1..4c33381b 100644 --- a/app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/incoming_upcoming_controller.rb @@ -4,12 +4,8 @@ class Api::V1::FetchBookingActions::IncomingUpcomingController < ApplicationCont def index head :no_content, status: 204 and return if current_api_v1_user.host_profile.nil? - accepted_bookings = Booking.where(status: "accepted", host_nickname: current_api_v1_user.nickname) - upcoming_bookings = - accepted_bookings - .select { |booking| booking.dates.last >= DateService.get_js_epoch } - .sort_by { |booking| booking.dates.first } - - render json: upcoming_bookings, each_serializer: Bookings::IndexSerializer, status: 200 + render json: Booking.get_upcoming_bookings_sorted(current_api_v1_user.nickname, nil), + each_serializer: Bookings::IndexSerializer, + status: 200 end end diff --git a/app/controllers/api/v1/fetch_booking_actions/outgoing_upcoming_controller.rb b/app/controllers/api/v1/fetch_booking_actions/outgoing_upcoming_controller.rb index 40d80b70..d12c0120 100644 --- a/app/controllers/api/v1/fetch_booking_actions/outgoing_upcoming_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/outgoing_upcoming_controller.rb @@ -2,12 +2,8 @@ class Api::V1::FetchBookingActions::OutgoingUpcomingController < ApplicationCont before_action :authenticate_api_v1_user!, only: %i[index] def index - accepted_bookings = Booking.where(status: "accepted", user_id: current_api_v1_user.id) - upcoming_bookings = - accepted_bookings - .select { |booking| booking.dates.last >= DateService.get_js_epoch } - .sort_by { |booking| booking.dates.first } - - render json: upcoming_bookings, each_serializer: Bookings::IndexSerializer, status: 200 + render json: Booking.get_upcoming_bookings_sorted(nil, current_api_v1_user.id), + each_serializer: Bookings::IndexSerializer, + status: 200 end end diff --git a/app/models/booking.rb b/app/models/booking.rb index ca10e3f8..7255278f 100644 --- a/app/models/booking.rb +++ b/app/models/booking.rb @@ -60,4 +60,20 @@ def self.get_request_bookings_sorted(host_nickname, user_id) ) return pending_bookings.sort_by { |booking| booking.created_at }.reverse end + + def self.get_upcoming_bookings_sorted(host_nickname, user_id) + accepted_bookings = + ( + if user_id.nil? + Booking.where(status: "accepted", host_nickname: host_nickname) + else + Booking.where(status: "accepted", user_id: user_id) + end + ) + upcoming_bookings = + accepted_bookings + .select { |booking| booking.dates.last >= DateService.get_js_epoch } + .sort_by { |booking| booking.dates.first } + return upcoming_bookings + end end From 41a4999eb3c0d18a5259f0bb58d66626752895f3 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Sat, 4 Feb 2023 19:12:51 +0200 Subject: [PATCH 27/32] Extracts logic of stats in model method. Relevant specs passing. --- .../incoming_stats_controller.rb | 19 +------ .../outgoing_stats_controller.rb | 17 +----- app/models/booking.rb | 55 +++++++++++++++++++ 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/app/controllers/api/v1/fetch_booking_actions/incoming_stats_controller.rb b/app/controllers/api/v1/fetch_booking_actions/incoming_stats_controller.rb index c6face60..aa09d1c4 100644 --- a/app/controllers/api/v1/fetch_booking_actions/incoming_stats_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/incoming_stats_controller.rb @@ -4,23 +4,6 @@ class Api::V1::FetchBookingActions::IncomingStatsController < ApplicationControl def index head :no_content, status: 204 and return if current_api_v1_user.host_profile.nil? - pending_bookings = Booking.where(status: "pending", host_nickname: current_api_v1_user.nickname).size - unpaid_bookings = Booking.where(status: "accepted", host_nickname: current_api_v1_user.nickname, paid: false).size - history_bookings_declined_canceled = - Booking.where(status: %w[declined canceled], host_nickname: current_api_v1_user.nickname).size - accepted_bookings = Booking.where(status: "accepted", host_nickname: current_api_v1_user.nickname).select("dates") - - upcoming_bookings = accepted_bookings.select { |booking| booking.dates.last >= DateService.get_js_epoch }.size - history_bookings_accepted = accepted_bookings.size - upcoming_bookings - - render json: { - stats: { - in_requests: pending_bookings, - in_upcoming: upcoming_bookings, - in_history: history_bookings_accepted + history_bookings_declined_canceled, - in_unpaid: unpaid_bookings - } - }, - status: 200 + render json: Booking.get_booking_stats(current_api_v1_user.nickname, nil), status: 200 end end diff --git a/app/controllers/api/v1/fetch_booking_actions/outgoing_stats_controller.rb b/app/controllers/api/v1/fetch_booking_actions/outgoing_stats_controller.rb index 0e04073b..4cff17b0 100644 --- a/app/controllers/api/v1/fetch_booking_actions/outgoing_stats_controller.rb +++ b/app/controllers/api/v1/fetch_booking_actions/outgoing_stats_controller.rb @@ -2,21 +2,6 @@ class Api::V1::FetchBookingActions::OutgoingStatsController < ApplicationControl before_action :authenticate_api_v1_user!, only: %i[index] def index - pending_bookings = Booking.where(status: "pending", user_id: current_api_v1_user.id).size - history_bookings_declined_canceled = - Booking.where(status: %w[declined canceled], user_id: current_api_v1_user.id).size - accepted_bookings = Booking.where(status: "accepted", user_id: current_api_v1_user.id).select("dates") - - upcoming_bookings = accepted_bookings.select { |booking| booking.dates.last >= DateService.get_js_epoch }.size - history_bookings_accepted = accepted_bookings.size - upcoming_bookings - - render json: { - stats: { - out_requests: pending_bookings, - out_upcoming: upcoming_bookings, - out_history: history_bookings_accepted + history_bookings_declined_canceled - } - }, - status: 200 + render json: Booking.get_booking_stats(nil, current_api_v1_user.id), status: 200 end end diff --git a/app/models/booking.rb b/app/models/booking.rb index 7255278f..8a5fa9dd 100644 --- a/app/models/booking.rb +++ b/app/models/booking.rb @@ -76,4 +76,59 @@ def self.get_upcoming_bookings_sorted(host_nickname, user_id) .sort_by { |booking| booking.dates.first } return upcoming_bookings end + + def self.get_booking_stats(host_nickname, user_id) + pending_bookings = + ( + if user_id.nil? + Booking.where(status: "pending", host_nickname: host_nickname).size + else + Booking.where(status: "pending", user_id: user_id).size + end + ) + unpaid_bookings = + user_id.nil? ? Booking.where(status: "accepted", host_nickname: host_nickname, paid: false).size : 0 + history_bookings_declined_canceled = + ( + if user_id.nil? + Booking.where(status: %w[declined canceled], host_nickname: host_nickname).size + else + Booking.where(status: %w[declined canceled], user_id: user_id).size + end + ) + accepted_bookings = + ( + if user_id.nil? + Booking.where(status: "accepted", host_nickname: host_nickname).select("dates") + else + Booking.where(status: "accepted", user_id: user_id).select("dates") + end + ) + + upcoming_bookings = accepted_bookings.select { |booking| booking.dates.last >= DateService.get_js_epoch }.size + history_bookings_accepted = accepted_bookings.size - upcoming_bookings + + if user_id.nil? + return( + { + stats: { + in_requests: pending_bookings, + in_upcoming: upcoming_bookings, + in_history: history_bookings_accepted + history_bookings_declined_canceled, + in_unpaid: unpaid_bookings + } + }.to_json + ) + end + + return( + { + stats: { + out_requests: pending_bookings, + out_upcoming: upcoming_bookings, + out_history: history_bookings_accepted + history_bookings_declined_canceled + } + }.to_json + ) + end end From cce0c27acf7e051b01d92700d2924f672a4f25b4 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Mon, 6 Feb 2023 13:40:37 +0200 Subject: [PATCH 28/32] Add more test scenarios to make sure begin works correctly --- spec/tasks/pay_the_host_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/spec/tasks/pay_the_host_spec.rb b/spec/tasks/pay_the_host_spec.rb index c57e31f2..de7fe5be 100644 --- a/spec/tasks/pay_the_host_spec.rb +++ b/spec/tasks/pay_the_host_spec.rb @@ -68,6 +68,9 @@ before do @subject = task.execute + unpaid_accepted_booking_past.reload + unpaid_accepted_booking_future.reload + paid_accepted_booking.reload @jobs = Delayed::Job.all end @@ -86,5 +89,17 @@ it "logs to stdout (stripe error)" do expect(@std_output).to match("No such destination:") end + + it "does not update an eligible to be paid unpaid booking" do + expect(unpaid_accepted_booking_past.paid).to eq false + end + + it "does not update future booking" do + expect(unpaid_accepted_booking_future.paid).to eq false + end + + it "does not update an already paid booking" do + expect(paid_accepted_booking.paid).to eq true + end end end From a393cf592797fdad175d866f80cfba35ca1e0289 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Mon, 6 Feb 2023 15:24:01 +0200 Subject: [PATCH 29/32] Typo fix in method name --- app/controllers/api/v1/bookings_controller.rb | 2 +- app/services/booking_service.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/v1/bookings_controller.rb b/app/controllers/api/v1/bookings_controller.rb index 08e31254..132f3bf5 100644 --- a/app/controllers/api/v1/bookings_controller.rb +++ b/app/controllers/api/v1/bookings_controller.rb @@ -54,7 +54,7 @@ def update begin !Rails.env.test? && Stripe::PaymentIntent.capture(booking.payment_intent_id) - BookingService.cancel_same_date_pending_bookings_on_upate(host, booking.dates, booking.id) + BookingService.cancel_same_date_pending_bookings_on_update(host, booking.dates, booking.id) booking.update( host_description: profile.description, host_full_address: profile.full_address, diff --git a/app/services/booking_service.rb b/app/services/booking_service.rb index b062b9b8..53f54b93 100644 --- a/app/services/booking_service.rb +++ b/app/services/booking_service.rb @@ -23,7 +23,7 @@ def self.get_host_unavailable_dates(host_profile_id) host_booked_dates.flatten.sort end - def self.cancel_same_date_pending_bookings_on_upate(host, booking_to_update_dates, booking_to_update_id) + def self.cancel_same_date_pending_bookings_on_update(host, booking_to_update_dates, booking_to_update_id) host_bookings = Booking.where(host_nickname: host.nickname, status: "pending") if !host_bookings.empty? From 698c33d86a96eede2a2d1d25c70b1a4446d92d52 Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Mon, 6 Feb 2023 15:28:39 +0200 Subject: [PATCH 30/32] Changes render order in create action --- app/controllers/api/v1/reviews_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/v1/reviews_controller.rb b/app/controllers/api/v1/reviews_controller.rb index d9066730..7c8371c7 100644 --- a/app/controllers/api/v1/reviews_controller.rb +++ b/app/controllers/api/v1/reviews_controller.rb @@ -26,8 +26,8 @@ def create host = User.find_by(nickname: booking.host_nickname) user = User.find(booking.user_id) - render json: { message: I18n.t("controllers.reusable.create_success") }, status: 200 ReviewsMailer.delay(queue: "reviews_email_notifications").notify_host_create_review(host, booking, user, review) + render json: { message: I18n.t("controllers.reusable.create_success") }, status: 200 end def update From a0e1c4403e99b28b5bd1f684676dedb0ba5a874a Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Mon, 6 Feb 2023 15:47:12 +0200 Subject: [PATCH 31/32] Further begin-rescue block updates --- app/controllers/api/v1/bookings_controller.rb | 7 ++++--- lib/tasks/bookings.rake | 11 ++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/v1/bookings_controller.rb b/app/controllers/api/v1/bookings_controller.rb index 132f3bf5..35c82e8e 100644 --- a/app/controllers/api/v1/bookings_controller.rb +++ b/app/controllers/api/v1/bookings_controller.rb @@ -54,6 +54,10 @@ def update begin !Rails.env.test? && Stripe::PaymentIntent.capture(booking.payment_intent_id) + rescue Stripe::StripeError + booking.update(status: "pending", host_message: nil) + render json: { errors: [I18n.t("controllers.reusable.stripe_error")] }, status: 400 + else BookingService.cancel_same_date_pending_bookings_on_update(host, booking.dates, booking.id) booking.update( host_description: profile.description, @@ -66,9 +70,6 @@ def update profile.update(availability: new_availability) BookingsMailer.delay(queue: "bookings_email_notifications").notify_user_accepted_booking(host, booking, user) render json: { message: I18n.t("controllers.bookings.update_success") }, status: 200 - rescue Stripe::StripeError - booking.update(status: "pending", host_message: nil) - render json: { errors: [I18n.t("controllers.reusable.stripe_error")] }, status: 400 end rescue ActiveRecord::RecordNotFound render json: { errors: [I18n.t("controllers.bookings.update_error")] }, status: 400 diff --git a/lib/tasks/bookings.rake b/lib/tasks/bookings.rake index dc4069c9..53e802b8 100644 --- a/lib/tasks/bookings.rake +++ b/lib/tasks/bookings.rake @@ -48,17 +48,18 @@ namespace :bookings do } } ) + rescue Stripe::StripeError => error + print error + StripeMailer.delay(queue: "stripe_email_notifications").notify_stripe_webhook_error( + "Payment to host for booking id #{booking.id} failed" + ) + else booking.update(paid: true) if ENV["OFFICIAL"] == "yes" ReportsMailer.delay(queue: "financial_reports_email_notifications").bookings_revenue_and_vat(booking) else print "A report email was sent! Booking with id #{booking.id} successfully paid!" end - rescue Stripe::StripeError => error - print error - StripeMailer.delay(queue: "stripe_email_notifications").notify_stripe_webhook_error( - "Payment to host for booking id #{booking.id} failed" - ) end end end From 39523b64fc6b221a7bc608d74f75c0ead323e8fb Mon Sep 17 00:00:00 2001 From: raptorf1 Date: Mon, 6 Feb 2023 16:00:33 +0200 Subject: [PATCH 32/32] Task code rearrangement. All specs passing. --- lib/tasks/bookings.rake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/tasks/bookings.rake b/lib/tasks/bookings.rake index 53e802b8..c4764701 100644 --- a/lib/tasks/bookings.rake +++ b/lib/tasks/bookings.rake @@ -10,6 +10,9 @@ namespace :bookings do host = User.find_by(nickname: booking.host_nickname) booking.update_column(:status, "canceled") booking.update_column(:host_message, "cancelled by system") + print "Pending booking with id #{booking.id} succesfully cancelled!" + BookingsMailer.delay(queue: "bookings_email_notifications").notify_user_cancelled_booking(host, booking, user) + BookingsMailer.delay(queue: "bookings_email_notifications").notify_host_cancelled_booking(host, booking, user) begin Stripe::PaymentIntent.cancel(booking.payment_intent_id) rescue Stripe::StripeError => error @@ -18,9 +21,6 @@ namespace :bookings do booking.payment_intent_id ) end - print "Pending booking with id #{booking.id} succesfully cancelled!" - BookingsMailer.delay(queue: "bookings_email_notifications").notify_user_cancelled_booking(host, booking, user) - BookingsMailer.delay(queue: "bookings_email_notifications").notify_host_cancelled_booking(host, booking, user) end end end