property_hire/app/models/property.rb

163 lines
6.1 KiB
Ruby

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
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.nil? || 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