class Property include Mongoid::Document include Mongoid::Timestamps include OrbitTag::Taggable include OrbitCategory::Categorizable include Slug field :title, as: :slug_title, :localize => true field :property_usage, :localize => true field :note, :localize => true field :property_number field :can_be_hired, type: Boolean, default: true field :purchase_date, type: DateTime field :owners, type: Array, :default => [] field :other_owner field :owner_email field :owner_phone field :price field :other_location mount_uploader :image, ImageUploader # unavailibility fields field :set_unavailibility, type: Boolean, default: false field :start_time field :end_time field :weekdays, type: Array, default: [] field :start_date, type: DateTime field :end_date, type: DateTime field :description, :localize => true field :unavailibility_note, :localize => true belongs_to :property_location has_many :p_hires has_many :hire_email_sets, :autosave => true, :dependent => :destroy, :inverse_of => :property accepts_nested_attributes_for :hire_email_sets, :allow_destroy => true WEEKDAYS = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ] def get_location_name return self.property_location.nil? ? self.other_location : self.property_location.title end def owner_profiles MemberProfile.find(self.owners) rescue [] end def is_available_for_hire?(stime, etime) return true if self.set_unavailibility == false return true if self.weekdays.empty? return true if !self.start_date.nil? && (self.start_date > stime && self.start_date > etime) return true if !self.end_date.nil? && self.end_date < stime startt = self.start_date.nil? ? self.created_at : self.start_date endt = self.end_date.nil? && !startt.nil? ? (startt + 5.years) : self.end_date weekdays = self.weekdays.collect{|w| w.to_i} if !startt.nil? common_dates = (startt..endt) & (stime..etime) return true if common_dates.nil? time_weekdays = [] Property.time_iterate(common_dates.min, common_dates.max, 1.day) do |t| time_weekdays << t.wday end time_weekdays.uniq! weekdays = weekdays & time_weekdays return true if weekdays.blank? startt = DateTime.parse(stime.strftime("%Y-%m-%d " + self.start_time + Time.zone.to_s)) endt = DateTime.parse(etime.strftime("%Y-%m-%d " + self.end_time + Time.zone.to_s)) common_dates = (startt..endt) & (stime..etime) if common_dates.nil? return true else return false end end end def is_already_hired?(stime, etime, interval, recurring_end_date) phires = self.p_hires bookings_count = phires.where(:start_time.lte => stime,:end_time.gte => stime,:recurring => false).count + phires.where(:start_time.gte => stime,:end_time.lte => etime,:recurring => false).count +phires.where(:start_time.lte => etime,:end_time.gte => etime,:recurring => false).count available = true if bookings_count != 0 available = false end if available bookings = phires.where(:recurring_end_date.gte => stime, :recurring => true) + phires.where(:recurring => false,:recurring_end_date => nil) + phires.where(:recurring => false,:recurring_end_date.gte => stime) case interval when 'week' d_step = 1.week when 'month' d_step = 1.month else d_step = 0 end bookings.each do |booking| stime_tp = stime etime_tp = etime b_interval = booking.recurring_interval if (b_interval == 'month' || b_interval == 'week') && booking.recurring_end_date.nil? b_interval = nil end while true if b_interval == 'month' diff_month = booking.end_time.month - booking.start_time.month diff_month = diff_month + 12 if diff_month < 0 e_month = stime_tp.month + diff_month e_year = stime_tp.year + (booking.end_time.year-booking.start_time.year) e_month = e_month - 12 if e_month >12 b_sdata = Time.local(stime_tp.year,stime_tp.month,booking.start_time.day,booking.start_time.hour,booking.start_time.minute).to_datetime b_edata = Time.local(e_year,e_month,booking.end_time.day,booking.end_time.hour,booking.end_time.minute).to_datetime elsif b_interval == 'week' diff_day = booking.end_time - booking.start_time if (booking.end_time.wday <= booking.start_time.wday && diff_day>1) || diff_day > 7 over_one_week = true end b_sdata_tp = stime_tp - stime_tp.wday.day + booking.start_time.wday.day b_sdata = Time.local(b_sdata_tp.year,b_sdata_tp.month,b_sdata_tp.day,booking.start_time.hour,booking.start_time.minute).to_datetime if over_one_week && etime_tp.wday <= booking.start_time.wday b_sdata = b_sdata - 7.day end now_diff_day = etime_tp - stime_tp if (etime_tp.wday <= stime_tp.wday && now_diff_day>1) || now_diff_day > 7 b_sdata = b_sdata + 7.day end b_edata_tp = b_sdata + (booking.end_time - booking.start_time).to_i.day b_edata = Time.local(b_edata_tp.year,b_edata_tp.month,b_edata_tp.day,booking.end_time.hour,booking.end_time.minute).to_datetime else b_sdata = booking.start_time b_edata = booking.end_time end sdata = stime_tp edata = etime_tp if etime_tp > booking.start_time if (sdata <= b_sdata && edata >= b_sdata) || (sdata >= b_sdata && edata <= b_edata) || (sdata <= b_edata && edata >= b_edata) available = false end end stime_tp = stime_tp + d_step etime_tp = etime_tp + d_step break if recurring_end_date.blank? || recurring_end_date < stime_tp end break if available == false end end return available end def self.time_iterate(start_time, end_time, step, &block) begin yield(start_time, end_time) end while (start_time += step) <= end_time end end