SQL запрос рельсов, как отфильтровать наше текущее бронирование - PullRequest
1 голос
/ 10 января 2020

В приложении для отеля я пытаюсь отфильтровать все доступные варианты размещения на определенную дату приезда и отъезда, поэтому пользователь видит их только как варианты.

Способ, которым я в настоящее время go говорю об этом, заключается в том, чтобы сначала определить все недоступные помещения, а затем вычесть их из всех помещений.

Вопрос

Когда я хочу изменить бронирование, я бы хотел:

  • исключить текущее бронирование при оценке доступных мест

==> поэтому в @unavailable_accommodations резервирование и его размещение для reservation.arrival и reservation.departure не оцениваются в операторе запроса

Возможно ли это, или как еще я могу добиться, чтобы получить доступное жилье только для прибывающего и отбывающего лица без учета текущего бронирования. Размещение:

Пример желаемого результата

  • Скажем, что оговорка_1 бронирует проживание_1 с 1 января по 2 января.
  • Затем есть оговорка_2, которая бронирует проживание_1 с 5 января по 6 января.
  • Когда я впоследствии изменяю оговорку_1 и изменяю отъезд до 6 января, размещение_1 должно , а не быть помечено как доступное как уже оговорено_2, забронировало это размещение

код

модели

class Reservation < ApplicationRecord
  belongs_to :hotel
  belongs_to :accommodation
end

class Accommodation < ApplicationRecord
  belongs_to :accommodation_category
  has_many :reservations, dependent: :destroy
  accepts_nested_attributes_for :accommodation_category
end

class Hotel < ApplicationRecord
  has_many :accommodation_categories, dependent: :destroy
  has_many :accommodations, through: :accommodation_categories
  has_many :reservations, dependent: :destroy
end

Запрос

@unavailable_accommodations = Accommodation.joins(:reservations).where(reservations: {hotel: hotel}).where("reservations.arrival <= ? AND ? <= reservations.departure", arrival, departure)
.or(Accommodation.joins(:reservations).where(reservations: {hotel: hotel}).where("reservations.arrival >= ? AND ? >= reservations.departure", arrival, departure)).distinct

действие контроллера


def accommodations_availability
#check if there was an accommodation for this reservation
    if !params[:reservation].nil?
      reservation = Reservation.find(params[:reservation])
      @prev_accommodation = reservation.accommodation
      @previous_cat = @prev_accommodation.accommodation_category
    end
    hotel = Hotel.includes(:accommodations).find(params[:id])
    arrival = Date.parse(accommodation_params[:arrival])
    departure = Date.parse(accommodation_params[:departure])
    time_span = arrival..departure

    #SQL statement
    @unavailable_accommodations = Accommodation.joins(:reservations).where(reservations: {hotel: hotel}).where("reservations.arrival <= ? AND ? <= reservations.departure", arrival, departure)
    .or(Accommodation.joins(:reservations).where(reservations: {hotel: hotel}).where("reservations.arrival >= ? AND ? >= reservations.departure", arrival, departure)).distinct


    @hotel_cats = hotel.accommodation_categories
    @hotel_accos = Accommodation.where(accommodation_category: @hotel_cats)
    @accommodations = @hotel_accos - @unavailable_accommodations
    @available_cats = []
    @accommodations.each do |acco|
      if !@available_cats.include? acco.accommodation_category
        @available_cats << acco.accommodation_category
      end
    end

    respond_to do |format|
      format.js
    end
  end

Ответы [ 2 ]

1 голос
/ 10 января 2020

Почему бы не сделать это просто:

@current_reservation = Reservation.find(params[:id]) # whatever it is
@unavailable_accommodations = your_query1
@available_accommodations = your_query2 - [@current_reservation.accommodation]

ОБНОВЛЕНИЕ:

Может быть решение на стороне контроллера, но у меня есть ощущение, что такая вещь должна быть обработанным также на входном конце.

Предложение: Как насчет того, чтобы передать предыдущее отправление бронирования current_accommodation и следующее прибытие бронирования при заполнении формы обновления. Таким образом, вы можете ограничить редактирование полей TimeDate, добавив минимальное и максимальное значения к обоим. Надеюсь, вы поняли.

Добавление проверки на сервере все равно будет важно с точки зрения дизайна (безопасности). Я подумаю об этом и снова обновлюсь, надеюсь:)

Обновление 2: (комментарий под вопросом)

"Хорошо, я думаю, что это проблема с ваш дизайн, то есть вы вычисляете available_accommodations в запросе, но то, что вы на самом деле показываете пользователю, - available_reservations. Вот почему так сложно представить себе проблему в уме. Я надеюсь, что вы думаете с этой точки зрения. изменить дизайн (вы можете показать пользователю доступное жилье, но запрос должен быть больше о бронировании за сценой). "

0 голосов
/ 23 января 2020

Вы можете отфильтровать все доступные варианты размещения в одном запросе:

@available_accommodations = Accommodation.joins(
"LEFT OUTER JOIN accommodations
 ON (reservations.hotel_id = accommodations.hotel.id
     AND reservations.accommodation_id = accommodations.id
     AND reservations.arrival <= ?
     AND reservations.departure >= ?)", departure, arrival)
.where("accommodations.hotel_id = ?", params[:id])
.where("reservations.id IS NULL")
.select("accommodations.*")

Ключевым моментом являются условия соединения reservations.arrival <= departure AND reservations.departure >= arrival. Это означает только присоединиться к договоренностям с прибытием или отъездом бронирования в диапазоне запрашиваемого прибытия и отъезда. А затем он отфильтровывает свободные места с reservations.id IS NULL в объединенном столе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...