From b2fd2e1b483a733a89f8d173131fe6784f03e53f Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 5 Jul 2022 16:11:45 +0200 Subject: [PATCH] build all slots at reservation creation time --- .../api/availabilities_controller.rb | 4 ++- app/controllers/api/trainings_controller.rb | 4 +-- .../availabilities/availabilities_service.rb | 32 ++++--------------- .../create_availabilities_service.rb | 9 ++++++ .../availabilities/reservations.json.jbuilder | 2 ++ ...eservation_fields_to_slots_reservations.rb | 6 ++-- .../20220705125232_insert_missing_slots.rb | 23 +++++++++++++ db/schema.rb | 4 +-- test/fixtures/slots.yml | 8 ----- test/fixtures/slots_reservations.yml | 8 +++++ ...iption_extension_after_reservation_test.rb | 2 ++ 11 files changed, 62 insertions(+), 40 deletions(-) create mode 100644 db/migrate/20220705125232_insert_missing_slots.rb diff --git a/app/controllers/api/availabilities_controller.rb b/app/controllers/api/availabilities_controller.rb index 9e2c524ee..fbcd58746 100644 --- a/app/controllers/api/availabilities_controller.rb +++ b/app/controllers/api/availabilities_controller.rb @@ -98,7 +98,9 @@ class API::AvailabilitiesController < API::ApiController def reservations authorize Availability - @reservation_slots = @availability.slots.includes(reservations: [statistic_profile: [user: [:profile]]]).order('slots.start_at ASC') + @reservation_slots = @availability.slots + .includes(slots_reservations: [reservations: [statistic_profile: [user: [:profile]]]]) + .order('slots.start_at ASC') end def export_availabilities diff --git a/app/controllers/api/trainings_controller.rb b/app/controllers/api/trainings_controller.rb index bb536cd88..b8902da78 100644 --- a/app/controllers/api/trainings_controller.rb +++ b/app/controllers/api/trainings_controller.rb @@ -52,8 +52,8 @@ class API::TrainingsController < API::ApiController authorize Training @training = Training.find(params[:id]) @availabilities = @training.availabilities - .includes(slots: { reservations: { statistic_profile: [:trainings, user: [:profile]] } }) - .where('slots.canceled_at': nil) + .includes(slots: { slots_reservations: { reservations: { statistic_profile: [:trainings, user: [:profile]] } } }) + .where('slots_reservations.canceled_at': nil) .order('availabilities.start_at DESC') end diff --git a/app/services/availabilities/availabilities_service.rb b/app/services/availabilities/availabilities_service.rb index 80f16414a..4342e2623 100644 --- a/app/services/availabilities/availabilities_service.rb +++ b/app/services/availabilities/availabilities_service.rb @@ -17,18 +17,9 @@ class Availabilities::AvailabilitiesService slots = [] availabilities.each do |a| - slot_duration = a.slot_duration || Setting.get('slot_duration').to_i - ((a.end_at - a.start_at) / slot_duration.minutes).to_i.times do |i| - next unless (a.start_at + (i * slot_duration).minutes) > DateTime.current || user.admin? - - slot = Slot.new( - start_at: a.start_at + (i * slot_duration).minutes, - end_at: a.start_at + (i * slot_duration).minutes + slot_duration.minutes, - availability_id: a.id, - availability: a, - machine: machine, - title: '' - ) + a.slots.each do |slot| + slot.machine = machine + slot.title = '' slot = @service.machine_reserved_status(slot, reservations, @current_user) slots << slot end @@ -44,18 +35,9 @@ class Availabilities::AvailabilitiesService slots = [] availabilities.each do |a| - slot_duration = a.slot_duration || Setting.get('slot_duration').to_i - ((a.end_at - a.start_at) / slot_duration.minutes).to_i.times do |i| - next unless (a.start_at + (i * slot_duration).minutes) > DateTime.current || user.admin? - - slot = Slot.new( - start_at: a.start_at + (i * slot_duration).minutes, - end_at: a.start_at + (i * slot_duration).minutes + slot_duration.minutes, - availability_id: a.id, - availability: a, - space: space, - title: '' - ) + a.slots.each do |slot| + slot.space = space + slot.title = '' slot = @service.space_reserved_status(slot, reservations, user) slots << slot end @@ -71,7 +53,7 @@ class Availabilities::AvailabilitiesService # first, we get the already-made reservations reservations = user.reservations.where("reservable_type = 'Training'") reservations = reservations.where('reservable_id = :id', id: training_id.to_i) if training_id.is_number? - reservations = reservations.joins(:slots).where('slots.start_at > ?', @current_user.admin? ? 1.month.ago : DateTime.current) + reservations = reservations.joins(slots_reservations: :slots).where('slots.start_at > ?', @current_user.admin? ? 1.month.ago : DateTime.current) # visible availabilities depends on multiple parameters availabilities = training_availabilities(training_id, user) diff --git a/app/services/availabilities/create_availabilities_service.rb b/app/services/availabilities/create_availabilities_service.rb index fb5f54474..567be4db2 100644 --- a/app/services/availabilities/create_availabilities_service.rb +++ b/app/services/availabilities/create_availabilities_service.rb @@ -4,6 +4,7 @@ class Availabilities::CreateAvailabilitiesService def create(availability, occurrences = []) availability.update_attributes(occurrence_id: availability.id) + slot_duration = availability.slot_duration || Setting.get('slot_duration').to_i occurrences.each do |o| next if availability.start_at == o[:start_at] && availability.end_at == o[:end_at] @@ -25,6 +26,14 @@ class Availabilities::CreateAvailabilitiesService slot_duration: availability.slot_duration, plan_ids: availability.plan_ids ).save! + + ((o.end_at - o.start_at) / slot_duration.minutes).to_i.times do |i| + Slot.new( + start_at: o.start_at + (i * slot_duration).minutes, + end_at: o.start_at + (i * slot_duration).minutes + slot_duration.minutes, + availability_id: o.id + ).save! + end end end end diff --git a/app/views/api/availabilities/reservations.json.jbuilder b/app/views/api/availabilities/reservations.json.jbuilder index c34226e2a..4bb1e67e7 100644 --- a/app/views/api/availabilities/reservations.json.jbuilder +++ b/app/views/api/availabilities/reservations.json.jbuilder @@ -1,3 +1,5 @@ +# frozen_string_literal: true + json.array!(@reservation_slots) do |slot| json.slot_id slot.id json.start_at slot.start_at.iso8601 diff --git a/db/migrate/20220704084929_add_reservation_fields_to_slots_reservations.rb b/db/migrate/20220704084929_add_reservation_fields_to_slots_reservations.rb index 87f5d5bab..80407eb3d 100644 --- a/db/migrate/20220704084929_add_reservation_fields_to_slots_reservations.rb +++ b/db/migrate/20220704084929_add_reservation_fields_to_slots_reservations.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Previously, the Slot table was holding data about reservations. # This was a wrong assumption that leads to a bug. # An Availability should have many slots but a slot can be related to multiple Reservations, @@ -8,7 +10,7 @@ class AddReservationFieldsToSlotsReservations < ActiveRecord::Migration[5.2] add_column :slots_reservations, :ex_start_at, :datetime add_column :slots_reservations, :ex_end_at, :datetime add_column :slots_reservations, :canceled_at, :datetime - add_column :slots_reservations, :offered, :boolean + add_column :slots_reservations, :offered, :boolean, default: false execute <<-SQL UPDATE slots_reservations @@ -90,7 +92,7 @@ class AddReservationFieldsToSlotsReservations < ActiveRecord::Migration[5.2] add_column :slots, :ex_start_at, :datetime add_column :slots, :ex_end_at, :datetime add_column :slots, :canceled_at, :datetime - add_column :slots, :offered, :boolean + add_column :slots, :offered, :boolean, default: false add_column :slots, :destroying, :boolean, default: false execute <<-SQL diff --git a/db/migrate/20220705125232_insert_missing_slots.rb b/db/migrate/20220705125232_insert_missing_slots.rb new file mode 100644 index 000000000..17f2a499b --- /dev/null +++ b/db/migrate/20220705125232_insert_missing_slots.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +# Previously, only the reserved slots were saved in DB, other slots were created on the fly. +# Now we save all slots in DB, so we must re-create slots for the existing availabilities +class InsertMissingSlots < ActiveRecord::Migration[5.2] + def up + Availability.all.each do |availability| + slot_duration = availability.slot_duration || Setting.get('slot_duration').to_i + + ((availability.end_at - availability.start_at) / slot_duration.minutes).to_i.times do |i| + Slot.find_or_create_by( + start_at: availability.start_at + (i * slot_duration).minutes, + end_at: availability.start_at + (i * slot_duration).minutes + slot_duration.minutes, + availability_id: availability.id + ) + end + end + end + + def down + Slot.where.not(id: SlotsReservation.all.map(&:slot_id)).each(&:destroy) + end +end diff --git a/db/schema.rb b/db/schema.rb index 767a17da4..f8f7df09e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2022_07_04_084929) do +ActiveRecord::Schema.define(version: 2022_07_05_125232) do # These are extensions that must be enabled in order to support this database enable_extension "fuzzystrmatch" @@ -769,7 +769,7 @@ ActiveRecord::Schema.define(version: 2022_07_04_084929) do t.datetime "ex_start_at" t.datetime "ex_end_at" t.datetime "canceled_at" - t.boolean "offered" + t.boolean "offered", default: false t.index ["reservation_id"], name: "index_slots_reservations_on_reservation_id" t.index ["slot_id"], name: "index_slots_reservations_on_slot_id" end diff --git a/test/fixtures/slots.yml b/test/fixtures/slots.yml index 05f1ce142..515bc616d 100644 --- a/test/fixtures/slots.yml +++ b/test/fixtures/slots.yml @@ -6,10 +6,6 @@ slot_1: created_at: 2012-03-12 13:40:22.342717000 Z updated_at: 2012-03-12 13:40:22.342717000 Z availability_id: 12 - ex_start_at: - canceled_at: - ex_end_at: - offered: slot_2: id: 2 @@ -18,7 +14,3 @@ slot_2: created_at: 2015-06-10 11:20:01.341130000 Z updated_at: 2015-06-10 11:20:01.341130000 Z availability_id: 13 - ex_start_at: - canceled_at: - ex_end_at: - offered: diff --git a/test/fixtures/slots_reservations.yml b/test/fixtures/slots_reservations.yml index c531b981c..038302da9 100644 --- a/test/fixtures/slots_reservations.yml +++ b/test/fixtures/slots_reservations.yml @@ -3,7 +3,15 @@ one: slot_id: 1 reservation_id: 1 + ex_start_at: + canceled_at: + ex_end_at: + offered: two: slot_id: 2 reservation_id: 2 + ex_start_at: + canceled_at: + ex_end_at: + offered: diff --git a/test/services/subscription_extension_after_reservation_test.rb b/test/services/subscription_extension_after_reservation_test.rb index 25ec82036..a0a5f0607 100644 --- a/test/services/subscription_extension_after_reservation_test.rb +++ b/test/services/subscription_extension_after_reservation_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'test_helper' class SubscriptionExtensionAfterReservationTest < ActiveSupport::TestCase