893 lines
37 KiB
Ruby
893 lines
37 KiB
Ruby
class Property
|
|
include Mongoid::Document
|
|
include Mongoid::Timestamps
|
|
include OrbitTag::Taggable
|
|
include OrbitCategory::Categorizable
|
|
include Slug
|
|
|
|
FIELDSNAME=["hiring_person_email","hiring_person_number","hiring_person_name","reason_for_hire","note_for_hire","organization" ,"person_in_charge" ,"tel_of_person_in_charge" ,"department" ,"contact_person" ,"tel_of_contact_person" , "mobile_phone_of_contact_person" ,"contact_person_Email" ,"contact_person_department"]
|
|
field :need_change_tmp_reason, type: Boolean, default: false
|
|
field :need_hire_before, type: Integer, default: 0 #0代表沒有限制
|
|
field :need_hire_before_unit, type: String, default: "day" #month, day, hour, minute
|
|
field :custom_calendar_type, type: Integer, default: 0 #0=>預設, 1=> 顯示, 2=> 不顯示
|
|
field :custom_carousel_image_width, type: String, default: ""
|
|
field :display_img, :type => Boolean, :default => false
|
|
field :image_display_class, type: String, default: "full-size-img" #3 choices: full-size-img , pull-left , pull-right
|
|
field :order_position, type: Integer, default: -1
|
|
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_email_rule, type: Integer, default: 0 # 0 => owners, 1 => owner_email, 2 => owners + owner_email
|
|
field :owner_phone
|
|
field :price
|
|
field :other_location
|
|
field :p_hire_start_time, type: DateTime
|
|
field :p_hire_end_time, type: DateTime
|
|
field :p_open_start_time, type: DateTime
|
|
field :p_open_end_time, type: DateTime
|
|
field :p_display_start_time, type: DateTime
|
|
field :p_display_end_time, type: DateTime
|
|
field :recurring_enable, type: Boolean, :default => false
|
|
|
|
mount_uploader :image, ImageUploader
|
|
|
|
# unavailibility fields
|
|
field :can_hire_before_months, type: Integer, default: 0
|
|
field :set_availability, type: Boolean, default: false
|
|
field :set_unavailibility, type: Boolean, default: false
|
|
field :start_time
|
|
field :end_time
|
|
field :weekdays, type: Array, default: []
|
|
field :special_unavailable_dates, type: Array, default: []
|
|
field :special_unavailable_dates_title, type: Array, default: []
|
|
field :start_date, type: DateTime # unavailable start date
|
|
field :end_date, type: DateTime # unavailable end date
|
|
field :hours_restriction, type: Integer, default: 0
|
|
field :hours_restriction_duration, type: String
|
|
field :description, :localize => true
|
|
field :unavailibility_note, :localize => true
|
|
field :hiring_person_email, type: Hash, default: {"enable"=>"1","required"=>"true"}
|
|
field :hiring_person_number, type: Hash, default: {"enable"=>"1","required"=>"true"}
|
|
field :hiring_person_name, type: Hash, default: {"enable"=>"1","required"=>"true"}
|
|
field :reason_for_hire, type: Hash, default: {"enable"=>"1","required"=>"true"}
|
|
field :note_for_hire, type: Hash, default: {"enable"=>"1","required"=>"false"}
|
|
field :organization, type: Hash, default: {"enable"=>"1","required"=>"false"}
|
|
field :person_in_charge, type: Hash, default: {"enable"=>"1","required"=>"false"}
|
|
field :tel_of_person_in_charge, type: Hash, default: {"enable"=>"1","required"=>"false"}
|
|
field :department, type: Hash, default: {"enable"=>"1","required"=>"false"}
|
|
field :contact_person, type: Hash, default: {"enable"=>"1","required"=>"false"}
|
|
field :tel_of_contact_person, type: Hash, default: {"enable"=>"1","required"=>"false"}
|
|
field :mobile_phone_of_contact_person, type: Hash, default: {"enable"=>"1","required"=>"false"}
|
|
field :contact_person_Email, type: Hash, default: {"enable"=>"1","required"=>"false"}
|
|
field :contact_person_department, type: Hash, default: {"enable"=>"1","required"=>"false"}
|
|
field :enable_notes_selector , type: Boolean, default: false
|
|
field :notes_selector ,type: Hash, default: {}
|
|
field :enable_fields_sort , type: Boolean, default: false
|
|
field :custom_field_names, type: Array
|
|
field :default_field_names, type: Array
|
|
field :copy_id
|
|
field :except_clone_relations, :type=>Array, :default => []
|
|
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
|
|
has_many :p_hire_fields, :autosave => true, :dependent => :destroy
|
|
accepts_nested_attributes_for :p_hire_fields, :allow_destroy => true
|
|
has_many :property_field_sets, :autosave => true, :dependent => :destroy
|
|
accepts_nested_attributes_for :property_field_sets, :allow_destroy => true
|
|
has_many :property_day_settings, :autosave => true, :dependent => :destroy
|
|
accepts_nested_attributes_for :property_day_settings, :allow_destroy => true
|
|
has_many :property_carousel_images, :autosave => true, :dependent => :destroy
|
|
accepts_nested_attributes_for :property_carousel_images, :allow_destroy => true
|
|
has_many :property_files, :autosave => true, :dependent => :destroy
|
|
accepts_nested_attributes_for :property_files, :allow_destroy => true
|
|
has_many :property_links, :autosave => true, :dependent => :destroy
|
|
accepts_nested_attributes_for :property_links, :allow_destroy => true
|
|
scope :sort_order, ->{order_by([:created_at,:desc],[:order_position,:asc])}
|
|
scope :can_display, ->{any_of({:p_display_start_time.lt=>Time.now, :p_display_end_time.gt=>Time.now},{:p_display_start_time.lt=>Time.now, :p_display_end_time=>nil},{:p_display_start_time=>nil, :p_display_end_time=>nil})}
|
|
WEEKDAYS = [
|
|
"Sunday",
|
|
"Monday",
|
|
"Tuesday",
|
|
"Wednesday",
|
|
"Thursday",
|
|
"Friday",
|
|
"Saturday"
|
|
]
|
|
CAlENDARTYPE = ["default","display","not_display"]
|
|
after_initialize do
|
|
unless self.new_record?
|
|
save_flag = false
|
|
@no_validate = true
|
|
if self.default_field_names.nil?
|
|
self.default_field_names = self.get_all_fields(true)
|
|
save_flag = true
|
|
end
|
|
if self.custom_field_names.nil?
|
|
self.custom_field_names = self.get_all_fields(true)
|
|
save_flag = true
|
|
end
|
|
if save_flag
|
|
self.save
|
|
end
|
|
end
|
|
end
|
|
before_create do
|
|
max_position = self.class.max(:order_position)
|
|
max_position = -1 if max_position.nil?
|
|
self.order_position = max_position + 1
|
|
@no_validate = true
|
|
if self.copy_id.present?
|
|
self.clone_new(true)
|
|
self.created_at = DateTime.now
|
|
self.updated_at = DateTime.now
|
|
else
|
|
self.default_field_names = self.get_all_fields(true)
|
|
self.custom_field_names = self.get_all_fields(true)
|
|
end
|
|
end
|
|
before_save do
|
|
unless @no_validate || self.new_record?
|
|
self.custom_field_names = [] if self.custom_field_names.nil?
|
|
self.default_field_names = self.get_all_fields(true)
|
|
self.class::FIELDSNAME.each do |f|
|
|
if((self.send(f)["enable"] == "1" rescue true) && !(self.custom_field_names.include?(f)))
|
|
self.custom_field_names << f
|
|
end
|
|
end
|
|
end
|
|
end
|
|
after_save do
|
|
self.change_day_setting_status
|
|
end
|
|
|
|
def can_reserve
|
|
now = Time.now
|
|
start_time = self.p_hire_start_time || now
|
|
end_time = self.p_hire_end_time || now
|
|
return now >= start_time && end_time >= now
|
|
end
|
|
|
|
def p_hire_fields_enabled
|
|
self.p_hire_fields.where(disabled: false)
|
|
end
|
|
def all_day_settings
|
|
self.property_day_settings.asc(:key).group_by(&:day)
|
|
end
|
|
def change_day_setting_status
|
|
if self.property_day_settings.count != 0
|
|
if self.set_unavailibility && self.weekdays.count != 0
|
|
self.property_day_settings.where(:day.nin=>self.weekdays).update_all(:enable=>true)
|
|
tmp_start_time = self.start_time.blank? ? "00:00" : self.start_time
|
|
tmp_end_time = self.end_time.blank? ? "24:00" : self.end_time
|
|
self.property_day_settings.where(:day.in=>self.weekdays).each do |setting|
|
|
if setting.end_time < tmp_start_time || setting.start_time > tmp_end_time
|
|
setting.enable = true
|
|
else
|
|
setting.enable = false
|
|
end
|
|
setting.save
|
|
end
|
|
else
|
|
self.property_day_settings.update_all(:enable=>true)
|
|
end
|
|
end
|
|
end
|
|
def calendar_type
|
|
(self.custom_calendar_type == 0 ? (PropertyHireSetting.first.calendar_type rescue 0) : (self.custom_calendar_type - 1))
|
|
end
|
|
def self.init_class_variables
|
|
setting = PropertyHireSetting.first
|
|
if setting
|
|
@@disable_content_page = setting.disable_content_page rescue false
|
|
@@disable_view_calendar_page = setting.disable_view_calendar_page rescue false
|
|
@@disable_no_logins_view_calendar = setting.disable_no_logins_view_calendar rescue false
|
|
else
|
|
@@disable_content_page = false
|
|
@@disable_view_calendar_page = false
|
|
@@disable_no_logins_view_calendar = false
|
|
end
|
|
end
|
|
init_class_variables
|
|
def disable_content_page
|
|
@@disable_content_page
|
|
end
|
|
def disable_view_calendar_page
|
|
@@disable_view_calendar_page
|
|
end
|
|
def disable_no_logins_view_calendar
|
|
@@disable_no_logins_view_calendar
|
|
end
|
|
def custom_text(field_name,type="name",locale=nil)
|
|
locale = locale || I18n.locale
|
|
default_text = I18n.with_locale(locale){I18n.t("property_hire.#{field_name}")}
|
|
if (self.send(field_name)[type][locale.to_s].present? rescue false)
|
|
self.send(field_name)[type][locale.to_s]
|
|
else
|
|
default_text
|
|
end
|
|
end
|
|
def render_unavailable_message
|
|
message = ""
|
|
property = self
|
|
weekdays_options = self.class::WEEKDAYS
|
|
weekdays_options = weekdays_options.map do |weekday|
|
|
trans = I18n.t("property_hire.#{weekday}", :default=>'')
|
|
if trans != ""
|
|
trans
|
|
else
|
|
weekday
|
|
end
|
|
end
|
|
if property.set_unavailibility
|
|
if property.weekdays.length > 0
|
|
translation_missing = (I18n.t('property_hire.unavailable_hint1', {:default => ''}) == "")
|
|
str1 = (!property.start_date.nil? ? (I18n.t("property_hire.from",:default=>" from ") + property.start_date.strftime("%Y-%m-%d")) : "")
|
|
str2 = (!property.end_date.nil? ? (I18n.t("property_hire.to",:default=>" to ") + property.end_date.strftime("%Y-%m-%d")) : "")
|
|
if str1 == "" && str2 != ""
|
|
str1 = I18n.t("property_hire.from_now_on")
|
|
end
|
|
if str1 != "" || str2 != ""
|
|
str2 += I18n.t("property_hire.of",:default=>"")
|
|
else
|
|
str2 += I18n.t("property_hire.at",:default=>"")
|
|
end
|
|
week_str = ""
|
|
if translation_missing
|
|
week_str += "every "
|
|
else
|
|
week_str += I18n.t("property_hire.every")
|
|
end
|
|
dot_trans = I18n.t("property_hire.dot",:default=>", ")
|
|
property.weekdays.each_with_index do |d,i|
|
|
if i < (property.weekdays.count - 1)
|
|
week_str += (weekdays_options[d.to_i] + dot_trans)
|
|
else
|
|
week_str += weekdays_options[d.to_i]
|
|
end
|
|
end
|
|
str3 = ""
|
|
if property.end_time.blank?
|
|
if property.start_time.blank?
|
|
str3 = "." if translation_missing
|
|
else
|
|
str3 = I18n.t("property_hire.from_time",{:time=>property.start_time,:default=>" from #{property.start_time}."})
|
|
end
|
|
else
|
|
if I18n.locale.to_s != "zh_tw"
|
|
str3 = " between #{property.start_time} & #{property.end_time}."
|
|
else
|
|
str3 = I18n.t("property_hire.time1_to_time2",{:time1=>property.start_time,:time2=>property.end_time})
|
|
end
|
|
end
|
|
if str3 != ""
|
|
str3 = I18n.t("property_hire.of",:default=>"") + str3
|
|
end
|
|
hint1 = I18n.t('property_hire.unavailable_hint1', {:str1=>str1,:str2=>str2,:week_str=>week_str,:str3=>str3, :default => ''})
|
|
if hint1 == ""
|
|
message += "This property is unavaliable#{str1}#{str2} #{week_str}#{str3}"
|
|
else
|
|
message += hint1
|
|
end
|
|
end
|
|
if property.special_unavailable_dates.count > 1
|
|
message += " And on " + property.special_unavailable_dates.join(", ")
|
|
end
|
|
if property.need_hire_before != 0
|
|
if message != ""
|
|
message += "<br>"
|
|
end
|
|
default_msg = "This property must be reserved #{property.need_hire_before} #{property.need_hire_before_unit}s in advance."
|
|
message += I18n.t("property_hire.unavailable_hint3",{:month=>property.need_hire_before,:unit=>I18n.t("property_hire._#{property.need_hire_before_unit}",:default=>property.need_hire_before_unit),:default=>default_msg})
|
|
end
|
|
if property.can_hire_before_months != 0
|
|
if message != ""
|
|
message += "<br>"
|
|
end
|
|
default_msg = "This property is unavaliable to reserved before #{property.can_hire_before_months} month ago."
|
|
message += I18n.t("property_hire.unavailable_hint2",{:month=>property.can_hire_before_months,:default=>default_msg})
|
|
end
|
|
if property.hours_restriction > 0
|
|
message += "<br />" + I18n.t("property_hire.hours_restriction_message", {:no_of_hours => property.hours_restriction, :duration => I18n.t("property_hire._#{property.hours_restriction_duration}") })
|
|
end
|
|
end
|
|
return message.html_safe
|
|
end
|
|
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 get_user_total_user_hired_hours(member_profile_id, start_time, end_time)
|
|
hires = self.p_hires.where(:hiring_person_id => member_profile_id, :start_time.gte => start_time, :end_time.lte => end_time)
|
|
total_hours = 0.0
|
|
hires.each do |hire|
|
|
diff = hire.end_time - hire.start_time
|
|
total_hours += diff * 24.0
|
|
end
|
|
return total_hours
|
|
end
|
|
|
|
def is_available_for_hire?(stime, etime, interval = nil, recurring_end_date = nil, time_setting_id = nil, member_profile)
|
|
available = 0
|
|
ma = ModuleApp.find_by_key("property_hire")
|
|
user = member_profile.user
|
|
is_user_manager = (user.is_admin? || user.is_manager?(ma) || user.is_sub_manager?(ma))
|
|
return 1 if is_user_manager == true
|
|
return 1 if self.set_unavailibility == false
|
|
return 1 if self.weekdays.empty? && self.can_hire_before_months == 0
|
|
time_now = Time.now.to_datetime
|
|
if self.can_hire_before_months != 0
|
|
return 2 if ((stime - (self.can_hire_before_months).month) > time_now)
|
|
end
|
|
if self.need_hire_before != 0
|
|
return 3 if (time_now + (self.need_hire_before).send(self.need_hire_before_unit) > stime)
|
|
end
|
|
self.special_unavailable_dates.each do |dt|
|
|
unavailable_date = Date.parse(dt)
|
|
cd = (stime..etime) & (unavailable_date..unavailable_date)
|
|
if !cd.nil?
|
|
return 0
|
|
end
|
|
end
|
|
|
|
startt = self.start_date.nil? ? stime : self.start_date
|
|
endt = self.end_date.nil? ? etime : self.end_date
|
|
|
|
if (stime >= startt) && (etime <= endt)
|
|
if self.hours_restriction > 0 && !user.nil?
|
|
sd = nil
|
|
edd = nil
|
|
case self.hours_restriction_duration
|
|
when "week"
|
|
sd = stime - stime.wday
|
|
edd = sd + 6
|
|
when "month"
|
|
sd = Date.new(stime.year, stime.month, 1)
|
|
edd = sd.next_month.prev_day
|
|
end
|
|
if self.get_user_total_user_hired_hours(member_profile.id.to_s, sd, edd) >= self.hours_restriction
|
|
return 0
|
|
end
|
|
end
|
|
end
|
|
available = 1 if startt > etime
|
|
available = 1 if endt < stime
|
|
weekdays = self.weekdays.collect{|w| w.to_i}
|
|
if !startt.nil?
|
|
if available == 0
|
|
common_dates = (startt..endt) & (stime..etime)
|
|
available = 1 if common_dates.nil?
|
|
if available == 0
|
|
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
|
|
if weekdays.blank?
|
|
available = 1
|
|
else
|
|
startt = DateTime.parse(stime.strftime("%Y-%m-%d " + (self.start_time.blank? ? "00:00" : self.start_time) + Time.zone.to_s))
|
|
endt = DateTime.parse(etime.strftime("%Y-%m-%d " + (self.end_time.blank? ? "23:59" : self.end_time) + Time.zone.to_s))
|
|
common_dates = (startt..endt) & (stime..etime)
|
|
available = common_dates.nil? ? 1 : 0
|
|
end
|
|
end
|
|
end
|
|
if available == 1
|
|
if !recurring_end_date.blank?
|
|
case interval
|
|
when 'week'
|
|
d_step = 1.week
|
|
when 'month'
|
|
d_step = 1.month
|
|
else
|
|
d_step = 0
|
|
end
|
|
if d_step != 0
|
|
if etime >= stime
|
|
Property.time_iterate(etime,recurring_end_date,d_step).each do |date_time|
|
|
new_etime = date_time
|
|
new_stime = stime + (new_etime - etime)
|
|
available = self.is_available_for_hire?(new_stime, new_etime, nil, nil)
|
|
break if available != 1
|
|
end
|
|
else
|
|
available = 0
|
|
end
|
|
end
|
|
end
|
|
return available
|
|
else
|
|
return available
|
|
end
|
|
end
|
|
end
|
|
|
|
def not_yet_hired?(stime, etime, interval, recurring_end_date,phire_id=nil,time_setting_id=nil)
|
|
phires = self.p_hires
|
|
stime = stime.utc
|
|
etime = etime.utc
|
|
bookings_count = 0
|
|
reservation_limit = 0
|
|
if time_setting_id
|
|
time_setting = PropertyDaySetting.find(time_setting_id)
|
|
etime = stime + 1.day
|
|
etime = etime.utc
|
|
reservation_limit = time_setting.reservation_limit
|
|
if reservation_limit == 0
|
|
return true
|
|
end
|
|
bookings_count = phires.where(:start_time.lte => stime,:end_time.gte => stime,:recurring => false,:id.ne=>phire_id,:property_day_setting_id=>time_setting_id).count
|
|
+ phires.where(:start_time.gte => stime,:end_time.lte => etime,:recurring => false,:id.ne=>phire_id,:property_day_setting_id=>time_setting_id).count
|
|
+phires.where(:start_time.lte => etime,:end_time.gte => etime,:recurring => false,:id.ne=>phire_id,:property_day_setting_id=>time_setting_id).count
|
|
if bookings_count < reservation_limit
|
|
bookings_count = 0
|
|
end
|
|
else
|
|
bookings_count = phires.where(:start_time.lte => stime,:end_time.gte => stime,:recurring => false,:id.ne=>phire_id).count
|
|
+ phires.where(:start_time.gte => stime,:end_time.lte => etime,:recurring => false,:id.ne=>phire_id).count
|
|
+phires.where(:start_time.lte => etime,:end_time.gte => etime,:recurring => false,:id.ne=>phire_id).count
|
|
end
|
|
available = true
|
|
if bookings_count != 0
|
|
available = false
|
|
end
|
|
if available
|
|
recurring_bookings = phires.where(:recurring_end_date.gte => stime, :recurring => true,:id.ne=>phire_id)
|
|
bookings = phires.where(:recurring => false,:recurring_end_date => nil,:id.ne=>phire_id)
|
|
case interval
|
|
when 'week'
|
|
d_step = 1.week
|
|
when 'month'
|
|
d_step = 1.month
|
|
else
|
|
d_step = 0
|
|
end
|
|
not_in_ids = bookings.any_of([{:end_time.lt=>stime},{:start_time.gt=>etime}]).pluck(:id)
|
|
bookings = bookings.where(:id.nin=>not_in_ids)
|
|
if time_setting_id
|
|
recurring_bookings = recurring_bookings.where(:property_day_setting_id=>time_setting_id)
|
|
bookings = recurring_bookings.where(:property_day_setting_id=>time_setting_id)
|
|
end
|
|
if true#d_step != 0
|
|
bookings += recurring_bookings
|
|
end
|
|
if time_setting_id
|
|
tmp = {}
|
|
stime_date = stime.strftime("%Y-%m-%d")
|
|
bookings = bookings.each_with_index do |booking,i|
|
|
if booking.date.wday != stime.wday
|
|
next
|
|
end
|
|
b_interval = booking.recurring_interval
|
|
b_recurring_end_date = booking.recurring_end_date ? booking.recurring_end_date.utc : nil
|
|
booking_date = booking.start_time.utc.strftime("%Y-%m-%d")
|
|
if (b_interval == 'month' || b_interval == 'week') && (booking.recurring_end_date.nil? || !booking.recurring)
|
|
b_interval = nil
|
|
end
|
|
if stime_date == booking_date
|
|
if tmp[booking_date].nil?
|
|
tmp[booking_date] = 0
|
|
end
|
|
tmp[booking_date] += 1
|
|
available = false if tmp[booking_date] > reservation_limit
|
|
end
|
|
break if available == false
|
|
if b_interval.present?
|
|
b_interval = (1).send(b_interval)
|
|
b_sdata = booking.start_time.utc
|
|
b_datas = Property.time_iterate(b_sdata,b_recurring_end_date,b_interval)
|
|
all_stime_datas = Property.time_iterate(stime,b_recurring_end_date,b_interval).map{|t| t.utc.strftime("%Y-%m-%d")}
|
|
b_datas.each do |b_data|
|
|
booking_date = b_data.utc.strftime("%Y-%m-%d")
|
|
if all_stime_datas.include?(booking_date)
|
|
if tmp[booking_date].nil?
|
|
tmp[booking_date] = 0
|
|
end
|
|
tmp[booking_date] += 1
|
|
available = false if tmp[booking_date] > reservation_limit
|
|
end
|
|
break if available == false
|
|
end
|
|
end
|
|
break if available == false
|
|
end
|
|
else
|
|
bookings.each_with_index do |booking,i|
|
|
stime_tp = stime.clone
|
|
etime_tp = etime.clone
|
|
b_interval = booking.recurring_interval
|
|
b_recurring_end_date = booking.recurring_end_date ? booking.recurring_end_date.utc : nil
|
|
b_sdata = booking.start_time.utc
|
|
b_edata = booking.end_time.utc
|
|
b_delta = b_edata - b_sdata
|
|
if (b_interval == 'month' || b_interval == 'week') && (booking.recurring_end_date.nil? || !booking.recurring)
|
|
b_interval = nil
|
|
end
|
|
b_datas = []
|
|
if b_interval.present?
|
|
b_interval = (1).send(b_interval)
|
|
b_datas = Property.time_iterate(b_edata,b_recurring_end_date,b_interval)
|
|
b_datas = b_datas.map{|b_end| [b_end-b_delta,b_end]}
|
|
start_index = b_datas.count
|
|
b_datas.each_with_index do |(b_start,b_end),i|
|
|
if b_start >= stime_tp || b_end <= etime_tp
|
|
start_index = i
|
|
break
|
|
end
|
|
end
|
|
b_datas = b_datas[start_index..-1].to_a.map{|b_start,b_end| (b_start..b_end)}
|
|
else
|
|
b_datas = [b_sdata..b_edata]
|
|
end
|
|
while b_datas.present?
|
|
available = b_datas.find{|b_range| b_range & (stime_tp..etime_tp)}.nil?
|
|
stime_tp = stime_tp + d_step
|
|
etime_tp = etime_tp + d_step
|
|
break if !available || recurring_end_date.blank? || d_step==0
|
|
start_index = b_datas.find_index{|b_range| b_range.first >= stime_tp}
|
|
if start_index
|
|
b_datas = b_datas[start_index..-1]
|
|
else
|
|
b_datas = []
|
|
end
|
|
end
|
|
break if available == false
|
|
end
|
|
end
|
|
end
|
|
return available
|
|
end
|
|
def check_require_fields(booking_p)
|
|
fields_name = self.get_all_fields
|
|
has_p_hire_fields = self.p_hire_fields_enabled.count != 0
|
|
p_hire_fields = {}
|
|
if has_p_hire_fields
|
|
p_hire_fields = self.p_hire_fields_enabled.map{|rf| [rf.id.to_s,rf]}.to_h
|
|
end
|
|
error_messages = ""
|
|
form_index = 0
|
|
cross_lang_types = ['select','date','radio_button','checkbox']
|
|
unfilled_text = I18n.t('property_hire.unfilled')
|
|
available_locales = I18n.available_locales
|
|
available_locales_trans = available_locales.map{|l| [l, I18n.t(l)]}.to_h
|
|
fields_name.each do |field_name|
|
|
if has_p_hire_fields && field_name.include?("p_hire_fields")
|
|
rf = p_hire_fields[field_name.sub("p_hire_fields.",'')]
|
|
if rf && rf.markup != 'hint_text' && rf.to_require
|
|
v = booking_p["p_hire_field_values_attributes"][form_index.to_s]['value']
|
|
if cross_lang_types.include?(rf.markup) || rf.get_data["cross_lang"] == "true"
|
|
if v.blank?
|
|
error_messages += "#{rf.title}: #{unfilled_text}\n"
|
|
end
|
|
else
|
|
available_locales.each do |l|
|
|
if (v[l].blank? rescue true)
|
|
error_messages += "#{rf.title}(#{available_locales_trans[l]}): #{unfilled_text}\n"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
form_index = form_index +1
|
|
else
|
|
field_setting = self.send(field_name)
|
|
if field_setting && field_setting["required"] == "true" && booking_p[field_name].blank?
|
|
error_messages += "#{self.custom_text(field_name,"name")}: #{unfilled_text}\n"
|
|
end
|
|
end
|
|
end
|
|
error_messages
|
|
end
|
|
def self.time_iterate(start_time, end_time, step, &block)
|
|
times = []
|
|
if block_given?
|
|
begin
|
|
times << start_time
|
|
yield(start_time, end_time)
|
|
end while (start_time += step) <= end_time
|
|
else
|
|
start_time = start_time.clone
|
|
begin
|
|
times << start_time
|
|
end while (start_time += step) <= end_time
|
|
end
|
|
times
|
|
end
|
|
def carousel_image_width
|
|
(self.custom_carousel_image_width.blank? ? PropertyHireSetting.first.carousel_image_width : self.custom_carousel_image_width) rescue "75%"
|
|
end
|
|
def get_attribute_value(attribute_field, p_hire_id)
|
|
PHireFieldValue.find_by(p_hire_field_id: attribute_field.id, p_hire_id: p_hire_id)
|
|
end
|
|
|
|
def get_attribute_values(attribute_type=nil)
|
|
@attribute_values = attribute_type.p_hire_field_values rescue nil
|
|
end
|
|
def get_value_from_field_id(field_id,attribute_type=nil)
|
|
values = get_attribute_values(attribute_type)
|
|
value = values.detect {|value| value.p_hire_field_id == field_id} rescue nil
|
|
value ? value : nil
|
|
end
|
|
def get_basic_fields
|
|
basic_fields = self.class::FIELDSNAME
|
|
basic_fields = basic_fields.select{|f| (self.send(f)["enable"] == "1" rescue true)}
|
|
end
|
|
def get_all_fields(get_default=false)
|
|
@default_field_names = nil if @default_field_names.nil?
|
|
if get_default
|
|
if @default_field_names.nil?
|
|
basic_fields = self.get_basic_fields
|
|
custom_fields = []
|
|
self.p_hire_fields_enabled.each do |p_hire_field|
|
|
unless p_hire_field.disabled
|
|
custom_fields << "p_hire_fields.#{p_hire_field.id}"
|
|
end
|
|
end
|
|
@default_field_names = basic_fields + custom_fields
|
|
end
|
|
return @default_field_names
|
|
else
|
|
self.enable_fields_sort ? self.custom_field_names : self.default_field_names
|
|
end
|
|
end
|
|
def can_be_hired_frontend
|
|
user = OrbitHelper.current_user
|
|
self.can_be_hired || (user && (user.is_admin? || (self.owners && self.owners.include?(user.member_profile_id))))
|
|
end
|
|
def can_be_show_frontend
|
|
user = OrbitHelper.current_user
|
|
(!disable_no_logins_view_calendar && self.can_be_hired) || user
|
|
end
|
|
def clone_new(clone_mode=false)
|
|
@records_all = {}
|
|
if clone_mode
|
|
clone_target = self.class.find(object.copy_id) rescue nil
|
|
else
|
|
clone_target = self
|
|
end
|
|
property,clone_target = clone_new_for_object(self,clone_target,clone_mode)
|
|
property
|
|
end
|
|
def fix_uploader(clone_relation, r, f)
|
|
return r.send(f).blank?
|
|
if !@clone_mode || (clone_relation[f].blank? && clone_relation.send(f).blank?)
|
|
clone_relation[f] = r[f]
|
|
if @clone_mode
|
|
clone_relation.send(f).retrieve_from_store!(r[f])
|
|
else
|
|
org_id = clone_relation.id
|
|
clone_relation.id = r.id
|
|
clone_relation.send(f).retrieve_from_store!(r[f])
|
|
clone_relation.id = org_id
|
|
end
|
|
source_filepath = r.send(f).file.file
|
|
if @clone_mode
|
|
dest_filepath = clone_relation.send(f).file.file
|
|
FileUtils.mkdir_p(File.dirname(dest_filepath))
|
|
FileUtils.cp(source_filepath,dest_filepath)
|
|
end
|
|
elsif (clone_relation.send(f).file rescue nil)
|
|
clone_relation[f] = File.basename(clone_relation.send(f).file.file.to_s)
|
|
end
|
|
end
|
|
def clone_new_for_object(object,clone_target=nil,clone_mode=false,fix_only=false)
|
|
@except_clone_relations ||= self.except_clone_relations
|
|
if clone_mode || fix_only
|
|
new_object = object
|
|
clone_target = object.class.find(object.copy_id) rescue nil if clone_target.nil?
|
|
else
|
|
clone_target = object if clone_target.nil?
|
|
new_object = object.dup
|
|
end
|
|
return if @except_clone_relations.include?(new_object.class.to_s.underscore)
|
|
@records_all["#{new_object.class.to_s.underscore}_ids"] = {} if @records_all["#{new_object.class.to_s.underscore}_ids"].nil?
|
|
begin
|
|
@records_all["#{new_object.class.to_s.underscore}_ids"][clone_target.id] = new_object
|
|
rescue
|
|
nil
|
|
end
|
|
if !clone_target.nil? && !new_object.nil?
|
|
unless fix_only
|
|
if clone_mode
|
|
initialize_fields = []
|
|
if new_object.fields.keys.include?("uid")
|
|
new_object.generate_uid
|
|
end
|
|
else
|
|
initialize_fields = ["uid","created_at","updated_at"]
|
|
end
|
|
initialize_fields.each do |f|
|
|
new_object.send("#{f}=",nil) if new_object.fields.keys.include?(f)
|
|
end
|
|
end
|
|
relations_fields = clone_target.relations.except("impressions").keys
|
|
all_fields = clone_target.fields.keys - relations_fields
|
|
all_fields = all_fields - relations_fields.map{|k| "#{k}_id"}
|
|
all_fields = all_fields - relations_fields.map{|k| "#{k.singularize}_ids"}
|
|
new_object_class_name = new_object.class.to_s.underscore
|
|
unless @parent_level
|
|
unsort_relation_keys = clone_target.relations.keys - ['taggings']
|
|
fields_to_delete = [new_object_class_name]
|
|
tmp_relations_fields = [new_object_class_name]
|
|
while relations_fields.count > 0
|
|
tmp_singularize_relations_fields = tmp_relations_fields.map{|f| f.singularize}
|
|
approve_append = nil
|
|
relations_fields.each do |k|
|
|
belongs_to_class = clone_target.relations[k].class_name.constantize.relations.select{|k,v| v.macro == :belongs_to}.keys
|
|
has_many_class = clone_target.relations[k].class_name.constantize.relations.select{|k,v| v.macro.to_s.start_with?('has') }.keys
|
|
if (belongs_to_class - tmp_singularize_relations_fields).count == 0
|
|
other_has_many_class = (has_many_class - unsort_relation_keys)
|
|
if other_has_many_class.count == 0
|
|
tmp_relations_fields << k
|
|
else
|
|
org_k = k.to_s
|
|
result = other_has_many_class.map do |k|
|
|
belongs_to_class = k.classify.constantize.relations.select{|kk,v| v.macro == :belongs_to}.keys
|
|
has_many_class = k.classify.constantize.relations.select{|kk,v| v.macro.to_s.start_with?('has') }.keys
|
|
if (belongs_to_class - tmp_singularize_relations_fields - [org_k]).count == 0
|
|
true
|
|
else
|
|
fields_to_delete = fields_to_delete.concat(belongs_to_class)
|
|
tmp_relations_fields.concat(belongs_to_class)
|
|
false
|
|
end
|
|
end
|
|
if result.select{|t| !t}.count == 0
|
|
if (fields_to_delete.map{|f| f.pluralize} - tmp_relations_fields).count == 0
|
|
tmp_relations_fields << k
|
|
elsif clone_target.relations[k].class_name.constantize.fields.keys.include?("key")
|
|
tmp_relations_fields << k
|
|
elsif (clone_target.relations[k].class_name.constantize.relations.keys.map{|f| f.singularize} & fields_to_delete).count != 0
|
|
approve_append = k
|
|
end
|
|
end
|
|
end
|
|
elsif !unsort_relation_keys.include?(clone_target.relations[k].class_name.underscore) && !unsort_relation_keys.include?(clone_target.relations[k].class_name.underscore.pluralize)
|
|
tmp_relations_fields << k
|
|
end
|
|
end
|
|
tmp_relations_fields << approve_append if approve_append.present?
|
|
approve_append = nil
|
|
relations_fields = relations_fields - tmp_relations_fields
|
|
relations_fields -= @relations_fields if @relations_fields
|
|
end
|
|
relations_fields = tmp_relations_fields
|
|
fields_to_delete.each{|f| relations_fields.delete(f)}
|
|
end
|
|
if @parent_level
|
|
relations_fields -= @relations_fields
|
|
else
|
|
@clone_mode = clone_mode
|
|
@relations_fields = relations_fields
|
|
end
|
|
@parent_level = true
|
|
if clone_mode
|
|
all_fields.each do |f|
|
|
next if f == "uid"
|
|
unless new_object.send("#{f}_changed?") && new_object.send("#{f}_changed_from_default?")
|
|
unless fix_only
|
|
new_object.send("#{f}=",clone_target.send(f))
|
|
end
|
|
if new_object.class.uploaders.include?(f.to_sym)
|
|
fix_uploader(new_object, clone_target, f)
|
|
end
|
|
end
|
|
end
|
|
else
|
|
all_fields.each do |f|
|
|
if new_object.class.uploaders.include?(f.to_sym)
|
|
fix_uploader(new_object, clone_target, f)
|
|
end
|
|
end
|
|
end
|
|
relations_fields.each do |f|
|
|
no_dup_flag = false
|
|
if clone_target.relations[f].macro == :belongs_to || clone_target.relations[f].macro == :has_one
|
|
no_dup_flag = new_object.send(f).present?
|
|
elsif clone_target.relations[f].macro == :has_many || clone_target.relations[f].macro == :has_and_belongs_to_many
|
|
no_dup_flag = new_object.send(f).to_a.count != 0
|
|
elsif clone_target.relations[f].macro == :embeds_many #Fix localize fields
|
|
if new_object.send(f).to_a.count != 0
|
|
need_fix_fields = new_object.send(f).to_a[0].fields.select{|k,v| (v.options[:localize] rescue false)}.keys
|
|
locale = I18n.locale.to_s
|
|
embeded_records = new_object.send(f).map do |embeded_record|
|
|
need_fix_fields.each do |f|
|
|
if (embeded_record[f][locale].class != String rescue false)
|
|
embeded_record.send("#{f}_translations=",embeded_record[f][locale])
|
|
else
|
|
embeded_record.send("#{f}_translations=",embeded_record[f])
|
|
end
|
|
end
|
|
embeded_record
|
|
end
|
|
new_object.send("#{f}=",embeded_records)
|
|
end
|
|
end
|
|
if clone_target.relations[f].macro == :belongs_to || clone_target.relations[f].class_name == "MemberProfile"
|
|
if f == 'taggable'
|
|
map_f = @taggable_name
|
|
else
|
|
map_f = f
|
|
end
|
|
if @records_all["#{map_f}_ids"].nil?
|
|
new_object.send("#{f}_id=",clone_target.send("#{f}_id"))
|
|
else
|
|
obj = @records_all["#{map_f}_ids"][clone_target.send("#{f}_id")]
|
|
if obj
|
|
new_object.send("#{f}_id=", obj.id)
|
|
new_object.send("#{f}=", obj)
|
|
end
|
|
end
|
|
elsif clone_target.relations[f].macro == :has_one
|
|
next if @except_clone_relations.include?(f)
|
|
need_clone_relation = clone_target.send(f)
|
|
next if need_clone_relation.nil?
|
|
clone_relation = new_object.send(f)
|
|
if clone_relation.nil?
|
|
clone_relation, need_clone_relation = clone_new_for_object(need_clone_relation.dup, need_clone_relation, clone_mode, fix_only)
|
|
else
|
|
clone_relation, r = clone_new_for_object(clone_relation, r, clone_mode, true)
|
|
end
|
|
new_object.send("#{f}=",clone_relation)
|
|
elsif clone_target.relations[f].macro == :has_many || clone_target.relations[f].macro == :has_and_belongs_to_many
|
|
next if @except_clone_relations.include?(f)
|
|
clone_relations = []
|
|
need_clone_relations = clone_target.send(f).asc(:_id).to_a
|
|
file_flag = false
|
|
if f == 'taggings'
|
|
@taggable_name = new_object.class.to_s.underscore
|
|
end
|
|
need_clone_relations.each_with_index do |r,i|
|
|
clone_relation = new_object.send(f)[i]
|
|
if clone_relation.nil?
|
|
clone_relation, r = clone_new_for_object(r.dup, r, clone_mode, fix_only)
|
|
else
|
|
clone_relation, r = clone_new_for_object(clone_relation, r, clone_mode, true)
|
|
end
|
|
clone_relations << clone_relation
|
|
end
|
|
if !no_dup_flag || (no_dup_flag && file_flag)
|
|
new_object_relations = new_object.send(f).to_a
|
|
new_object_relations_count = new_object_relations.count
|
|
if new_object_relations_count != 0
|
|
if clone_relations.count > new_object_relations_count
|
|
clone_relations = clone_relations[0...new_object_relations_count]
|
|
else
|
|
clone_relations = clone_relations.concat(new_object.send(f)[clone_relations.count...new_object_relations_count])
|
|
end
|
|
new_object.send("#{f}=",clone_relations)
|
|
else
|
|
new_object.send("#{f}=",clone_relations)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
new_object.copy_id = clone_target.id if new_object.fields.keys.include?("copy_id")
|
|
return new_object, clone_target
|
|
end
|
|
end
|
|
def get_owner_emails
|
|
emails = []
|
|
case self.owner_email_rule
|
|
when 0
|
|
emails = MemberProfile.where(:id.in=> self.owners.to_a).pluck(:email)
|
|
when 1
|
|
emails = [self.owner_email]
|
|
when 2
|
|
emails = MemberProfile.where(:id.in=> self.owners.to_a).pluck(:email) + [self.owner_email]
|
|
end
|
|
emails.select{|email| email.present?}
|
|
end
|
|
end
|