/nerdcalendar

Projeto de Gem para Sistemas que envolvem Reserva/aluguel

Primary LanguageRuby

#NerdCalendar

A ideia é fazer este projeto se tornar uma gem para auxiliar a construção de sistemas que envolvam locações ou reservas.

Um modelo que for 'reservável' não pode ser reservado duas vezes em um mesmo intervalo de tempo, para isso criei os models Reservable que representa qualquer objeto ou serviço que pode ser alugado e Reservation que serve para representar uma reserva e através do mesmo ser capaz de saber se um objeto já está reservado.

##Reservable

class Reservable < ActiveRecord::Base
	has_many :reservations
	scope :reserved_at_date, lambda{ |date = Date.today| joins(:bookings).where("? BETWEEN bookings.start_at AND bookings.end_at and bookings.hosted=?", date, false) }
	scope :busy_at_date, lambda{ |date = Date.today| joins(:bookings).where("? BETWEEN bookings.start_at AND bookings.end_at and bookings.hosted=?", date, true) }
	scope :free_at_date, lambda{ |date = Date.today| where("id NOT IN (SELECT room_id FROM bookings WHERE (? between start_at and end_at))", date) }

	def has_reservations_between_dates?(start_date, end_date)
		bookings.where(["(start_at BETWEEN :start_at AND :end_at OR end_at BETWEEN :start_at AND :end_at)", {:start_at=> start_date, :end_at=> end_date}]).exists?
	end 

	def has_reservations_at_dates?(start_at, end_at)
		return bookings.where("(? BETWEEN start_at AND end_at OR ? BETWEEN start_at AND end_at)", start_at,end_at).exists?
	end
end

##Reservation

class Reservation < ActiveRecord::Base
  belongs_to :reservable
  validates_presence_of :start_at, :end_at, :reservable_id
  validate :cannot_start_or_end_at_reserved_date, :cannot_end_at_be_less_than_start_at, :if => lambda{ |object| object.start_at.present? and object.end_at.present? }
  validate :cannot_start_at_past, :if => lambda{ |object| object.start_at.present? }
  validate :cannot_end_at_past, :if => lambda{ |object| object.end_at.present?}
  scope :excepts, lambda {|booking| where.not(:id=>booking.id)  }
  scope :between_dates, lambda{ |start_date = Date.today,end_date=Date.tomorrow| where(["(start_at BETWEEN :start_at AND :end_at OR end_at BETWEEN :start_at AND :end_at)", {:start_at=> start_date, :end_at=> end_date}]) }
  scope :at_dates, lambda{ |start_date = Date.today,end_date=Date.tomorrow| where("(? BETWEEN start_at AND end_at OR ? BETWEEN start_at AND end_at)", start_date,end_date) }

  before_save do
    self.start_at = self.start_at.to_date
    self.end_at = self.end_at.to_date
  end

  def cannot_start_or_end_at_reserved_date
    errors.add(:base, :invalid) if reservable.reservations.excepts(self).between_dates(start_at, end_at).exists? || reservable.reservations.excepts(self).at_dates(start_at, end_at).exists?
  end

  def cannot_end_at_be_less_than_start_at
    errors.add(:end_at, :inclusion) if end_at.before? start_at
  end
  
  def cannot_start_at_past
    errors.add(:start_at, :is_past) if self.start_at.is_past?
  end

  def cannot_end_at_past
    errors.add(:end_at, :is_past) if self.end_at.is_past?
  end
end

#O que precisa ser feito???

  • Obter o status se o objeto reservável está livre ou ocupado e se possível uma terceira situação, reservado, ou seja aquele que ainda não foi efetivamente usado mas está reservado.
  • Otimizar as queries e os mecanismos das validações.

Quem puder ajudar a contribuir pode se sentir a vontade, meu e-mail é renatosousafilho@gmail.com e twitter @renatosousafh.

#Dependências

rspec-rails
factory-girl
database_cleaner