From e199880f136488bdc92d8b9141e5ccc3dc53e58f Mon Sep 17 00:00:00 2001 From: Bohung Date: Wed, 8 Sep 2021 10:10:44 +0800 Subject: [PATCH] Update a lots.(include allow not logins user to hire, let admin set calendar display?,fix bugs) --- .../property_hire_calendar_frontend.js | 6 +- app/controllers/property_hires_controller.rb | 150 +++- app/helpers/admin/p_hire_field_helper.rb | 10 +- app/helpers/admin/property_hires_helper.rb | 4 + app/models/p_hire.rb | 21 +- app/models/p_hire_field.rb | 13 +- app/models/p_hire_field_value.rb | 24 +- app/models/property.rb | 57 +- app/models/property_day_setting.rb | 1 + app/models/property_hire_setting.rb | 2 + app/views/admin/property_hires/_form.html.erb | 12 +- .../admin/property_hires/edit_hire.html.erb | 758 ++++++++++++++---- .../admin/property_hires/settings.html.erb | 12 + app/views/admin/property_hires/show.html.erb | 2 +- .../show_booking_details.html.erb | 18 +- app/views/email/p_hire_email.html.erb | 15 +- app/views/property_hires/hire.html.erb | 160 ++-- config/locales/en.yml | 13 + config/locales/zh_tw.yml | 13 + config/routes.rb | 1 + property_hire.gemspec | 23 +- 21 files changed, 998 insertions(+), 317 deletions(-) diff --git a/app/assets/javascripts/property_hire_calendar_frontend.js b/app/assets/javascripts/property_hire_calendar_frontend.js index 13355fd..78a82c8 100644 --- a/app/assets/javascripts/property_hire_calendar_frontend.js +++ b/app/assets/javascripts/property_hire_calendar_frontend.js @@ -103,9 +103,10 @@ window.getDateString = function(date, format,is_chinese) { } return formattedDate; }; -var Calendar = function(dom,property_id,currentView){ +var Calendar = function(dom,property_id,currentView,display_hire_event){ c = this; + display_hire_event = (display_hire_event == undefined ? true : display_hire_event); this.title = $("#current_title"); this.calendar_dom = $(dom); this.nextBtn = $("#next_month_btn"); @@ -144,7 +145,8 @@ var Calendar = function(dom,property_id,currentView){ data: { start: Math.round(start.getTime() / 1000), end: Math.round(end.getTime() / 1000), - _: Date.now() + _: Date.now(), + display_hire_event: display_hire_event }, success: function(json) { // json = json.map(function(obj){ diff --git a/app/controllers/property_hires_controller.rb b/app/controllers/property_hires_controller.rb index a570860..c513bac 100644 --- a/app/controllers/property_hires_controller.rb +++ b/app/controllers/property_hires_controller.rb @@ -170,40 +170,66 @@ class PropertyHiresController < ApplicationController start_time = booking_p[:start_time] end_time = booking_p[:end_time] time_setting = nil + is_admin_page = (params[:url] == "admin") if time_setting_id.present? start_time = booking_p[:date] end_time = start_time time_setting = PropertyDaySetting.find(time_setting_id) if booking_p[:recurring_end_date].present? - booking_p[:recurring_end_date] = DateTime.parse(booking_p[:recurring_end_date].strftime('%Y-%m-%d') + time_setting.end_time + Time.zone.to_s) + booking_p[:recurring_end_date] = DateTime.parse(booking_p[:recurring_end_date].split(" ")[0] + ' ' + time_setting.end_time + Time.zone.to_s) + end + booking_p[:start_time] = booking_p[:date] + " " + time_setting.start_time + booking_p[:end_time] = booking_p[:date] + " " + time_setting.end_time + booking_p[:property_day_setting_id] = booking_p[:time] + booking_p.delete(:time) + end + property = Property.find(booking_p[:property_id]) rescue nil + begin + index_page = is_admin_page ? "/#{I18n.locale}/admin/property_hires/#{property.to_param}" : "/#{I18n.locale}#{params[:url]}/#{property.to_param}" + rescue + index_page = is_admin_page ? "/#{I18n.locale}/admin/property_hires" : "/#{I18n.locale}#{params[:url]}" + end + hire_page = is_admin_page ? request.referer : "#{index_page}?method=hire" + need_validate = (PropertyHireSetting.last.allow_no_logins_user rescue false) && current_user.nil? + session.delete(:hire_data) + if need_validate + unless gotcha_valid? + session[:hire_data] = booking_p + session["hire-save-msg"] = I18n.t("property_hire.recaptcha.errors.verification_failed") + if property.nil? + redirect_to index_page and return + else + redirect_to hire_page and return + end end end + if params[:url] == "admin" + params[:phire_id] = booking_p[:id] + end data = check_for_availability(start_time,end_time,booking_p[:property_id], booking_p[:recurring_interval], booking_p[:recurring_end_date], time_setting_id) - property = Property.find(booking_p[:property_id]) rescue nil if data["success"] == true - if time_setting_id.present? - booking_p[:start_time] = booking_p[:date] + " " + time_setting.start_time - booking_p[:end_time] = booking_p[:date] + " " + time_setting.end_time - booking_p[:property_day_setting_id] = booking_p[:time] - booking_p.delete(:time) - booking_p.delete(:date) + hire = nil + if params[:phire_id] + hire = PHire.find(params[:phire_id]) + hire.update_attributes(booking_p) + else + hire = PHire.new(booking_p) end - hire = PHire.new(booking_p) hire.passed = true if PropertyHireSetting.auto_approve_enabled? hire.save - if !property.nil? + if !property.nil? && !is_admin_page email = Array(MemberProfile.find(property.owners)).collect{|v| v.email} rescue [] email = User.all.select{|v| v.is_admin? && v.user_name != 'rulingcom'}.collect{|v| v.member_profile.email} if email.length == 0 email << hire.hiring_person_email Admin::PropertyHiresHelper::HireMethod.send_mail('p_hire',email,property.id,nil,hire.id) end - redirect_to params[:url] + redirect_to index_page else session["hire-save-msg"] = data["msg"] if property.nil? - redirect_to "/" + I18n.locale.to_s + params[:url] + redirect_to index_page else - redirect_to "/" + I18n.locale.to_s + params[:url] + "/#{property.to_param}?method=hire" + redirect_to hire_page end end end @@ -213,12 +239,31 @@ class PropertyHiresController < ApplicationController property = Property.where(:uid => params[:uid]).first rescue nil page = Page.where(:page_id => params[:page_id]).first return {} if property.nil? - hire = PHire.new + hire = nil + session = OrbitHelper.request.session rescue {} + recover = false + if (session[:hire_data] rescue false) + begin + hire = PHire.new({:id=>nil}.merge(session[:hire_data])) + recover = true + rescue => e + puts e.to_s + hire = PHire.new(:id=>nil) + end + else + hire = PHire.new(:id=>nil) + end + allow_no_logins_user = PropertyHireSetting.last.allow_no_logins_user + all_day_settings = property.all_day_settings.map{|d,settings| [d,settings.map{|s| [s.id.to_s,s.title]}]}.to_h { "hire" => hire, "property" => property, "page" => page.url, - "current_user" => OrbitHelper.current_user + "current_user" => OrbitHelper.current_user, + "allow_no_logins_user" => allow_no_logins_user, + "carousel_display_style" => "width: #{property.carousel_image_width};", + "all_day_settings" => all_day_settings, + "recover" => recover } end @@ -241,8 +286,18 @@ class PropertyHiresController < ApplicationController allevents = events.inject(re, :<<) allevents = allevents.sort_by{|e| e[:start]} @need_check_events = allevents.map{|e| [e[:date],e[:s_id]]} - if property.set_availability - all_day_settings = property.property_day_settings.asc(:key).group_by(&:day).map{|d,settings| [d,settings.map{|s| [s.start_time,s.end_time,s.id.to_s,s.title,s.reservation_limit]}]}.to_h + if property.set_availability && params[:display_hire_event] + check_setting = property.set_unavailibility && (property.property_day_settings.where(:enable=>false).count != 0) + @check_start_time = property.start_time.blank? ? "00:00" : property.start_time + @check_end_time = property.end_time.blank? ? "24:00" : property.end_time + @check_start_date = property.start_date + @check_end_date = property.end_date + if check_setting + if (@check_start_date > edt rescue false) || (@check_end_date > sdt rescue false) + check_setting = false + end + end + all_day_settings = property.all_day_settings.map{|d,settings| [d,settings.map{|s| [s.start_time,s.end_time,s.id.to_s,s.title,s.reservation_limit,s.enable]}]}.to_h if all_day_settings.count != 0 time_now = Time.zone.now get_start_time = [sdt,time_now].max @@ -251,7 +306,7 @@ class PropertyHiresController < ApplicationController if property.can_hire_before_months != 0 get_end_time = [time_now + (property.can_hire_before_months).send("month"),edt].min end - allevents += generate_all_reserve_buttons(get_start_time,get_end_time,all_day_settings) + allevents += generate_all_reserve_buttons(get_start_time,get_end_time,all_day_settings,check_setting) end end end @@ -263,11 +318,32 @@ class PropertyHiresController < ApplicationController end end def reserve_calendar_event(date,title,allow_times) - {:title=>title, :start=>date.to_s, :end => (date + 1.day).to_s, :allDay => true, :color => "#3788d8",:allow_times=>allow_times,:classNames=>["reserve_btn"]} + available = true + if @check_setting && !allow_times[5] + available = date > @check_end_date || date < @check_start_date + unless available + allow_times = allow_times.select do |allow_time| + if allow_time[0] > @check_end_time || allow_time[1] < @check_start_time + true + else + false + end + end + available = (allow_times.count != 0) + end + end + if available + {:title=>title, :start=>date.to_s, :end => (date + 1.day).to_s, :allDay => true, :color => "#3788d8",:allow_times=>allow_times,:classNames=>["reserve_btn"]} + else + {} + end end - def generate_all_reserve_buttons(startt,endt,all_day_settings) + def generate_all_reserve_buttons(startt,endt,all_day_settings,check_setting=false) + @check_setting = check_setting @display_title = I18n.t("property_hire.reserve") @allevents = [] + startt = startt.in_time_zone(Time.zone) + endt = endt.in_time_zone(Time.zone) start_wday = startt.wday start_date = startt.to_date @start_date = start_date @@ -285,18 +361,15 @@ class PropertyHiresController < ApplicationController if @all_day_settings.has_key?(wday_str) check_time = nil check_time = @first_check_time if is_start_day - i = -1 - if @need_check_events.count == 1 - if @need_check_events[0][0] <= @start_date - i = 0 - end - else - i = @need_check_events.index{|e| e[0] > @start_date} - if i.nil? + i = @need_check_events.index{|e| e[0] > @start_date} + if i.nil? + if @need_check_events.length != 0 && @need_check_events[-1][0] <= @start_date + i = @need_check_events.length - 1 + else i = -1 - elsif i != -1 - i -= 1 end + elsif i != -1 + i -= 1 end check_events = [] if i != -1 @@ -335,18 +408,15 @@ class PropertyHiresController < ApplicationController else @all_day_settings.each do |wday_str,settings| tmp_date = @start_date + wday_str.to_i.send("day") - i = -1 - if @need_check_events.count == 1 - if @need_check_events[0][0] <= tmp_date - i = 0 - end - else - i = @need_check_events.index{|e| e[0] > tmp_date} - if i.nil? + i = @need_check_events.index{|e| e[0] > tmp_date} + if i.nil? + if @need_check_events.length != 0 && @need_check_events[-1][0] <= tmp_date + i = @need_check_events.length - 1 + else i = -1 - elsif i != -1 - i -= 1 end + elsif i != -1 + i -= 1 end check_events = [] if i != -1 diff --git a/app/helpers/admin/p_hire_field_helper.rb b/app/helpers/admin/p_hire_field_helper.rb index fbf99f0..fc1bf7f 100644 --- a/app/helpers/admin/p_hire_field_helper.rb +++ b/app/helpers/admin/p_hire_field_helper.rb @@ -10,8 +10,9 @@ module Admin::PHireFieldHelper include OrbitFormHelper - def block_helper(member,index,disable = false,attribute_type=nil,p_hire=nil, to_require=true, col=2) + def block_helper(member,index,disable = false,attribute_type=nil,p_hire=nil, to_require=true, col=2, value=nil) unless self.disabled + return "" if self.title.blank? @col = col @index = index @require = to_require @@ -21,7 +22,7 @@ module Admin::PHireFieldHelper @attribute_type = attribute_type @new_attribute = @attribute_value.nil? @attribute_value = @attribute_value || p_hire.p_hire_field_values.build(p_hire_field_id: id) - @prefiled_value = @attribute_value.value rescue nil + @prefiled_value = value || @attribute_value.value rescue nil return instance_eval("render_#{markup}") rescue "" end end @@ -30,6 +31,8 @@ module Admin::PHireFieldHelper content_tag(:div,str,:class=>"tab-pane fade",:id=>(get_field_name_base+"tab_#{lang}")) end def render_hint_text + place_holder= self.get_placeholder rescue '' + return "" if place_holder.blank? control_group_wrapper do |key,value| if !@prefiled_value.nil? value = can_muti_lang_input? ? @prefiled_value[key] : @prefiled_value @@ -37,7 +40,6 @@ module Admin::PHireFieldHelper value = nil end key = can_muti_lang_input? ? "#{key}" : I18n.locale - place_holder= typeF["placeholder"][key] rescue '' name1 = "" text_area_tag(name1, place_holder,@markup_options.merge(:class=>'input-medium form-control',:readonly=>"",:rows=>"4")) end @@ -441,7 +443,7 @@ protected end def get_basic_field_name_org - "p_hire_field_values" + "p_hire[p_hire_field_values_attributes]" end def get_basic_field_name diff --git a/app/helpers/admin/property_hires_helper.rb b/app/helpers/admin/property_hires_helper.rb index 83f5c35..375589a 100644 --- a/app/helpers/admin/property_hires_helper.rb +++ b/app/helpers/admin/property_hires_helper.rb @@ -53,7 +53,11 @@ module Admin::PropertyHiresHelper I18n.with_locale(params[:locale]) do msg = I18n.t("property_hire.property_is_unavailable_during_this_time") if available_flag.nil? + if recurring_end_date.present? + stime = [stime,recurring_end_date].max + end can_hire_date = stime - (property.can_hire_before_months).month + puts "can_hire_date #{can_hire_date}" msg += ("
" + I18n.t("property_hire.please_hire_after_date",{:date=>"{#{can_hire_date.utc.to_json.gsub('"','')}}"})) else msg += ("
" + property.render_unavailable_message) diff --git a/app/models/p_hire.rb b/app/models/p_hire.rb index 0d974e0..087ea2e 100644 --- a/app/models/p_hire.rb +++ b/app/models/p_hire.rb @@ -29,6 +29,9 @@ class PHire belongs_to :property has_many :p_hire_field_values, :autosave => true, :dependent => :destroy accepts_nested_attributes_for :p_hire_field_values, allow_destroy: true + def property_day_setting + PropertyDaySetting.find(self.property_day_setting_id) rescue nil + end def as_json(options = {}) startt = self.start_time endt = self.end_time @@ -75,15 +78,15 @@ class PHire return MemberProfile.find(self.hiring_person_id) rescue nil end - def self.monthly_event(start_date,end_date,property_id,date_ony=false) + def self.monthly_event(start_date,end_date,property_id,date_only=false) events = self.where(:property_id => property_id, :recurring => false).any_of(:start_time.gte => start_date, :end_time.gte => start_date).and(:start_time.lte => end_date).asc(:start_time) - if date_ony + if date_only events = events.where(:date.ne=>nil) end events end - def self.recurring_event(start_date,end_date,property_id,date_ony=false) + def self.recurring_event(start_date,end_date,property_id,date_only=false) @property = Property.find(property_id) rescue nil @recurring = [] if @property != nil @@ -96,7 +99,7 @@ class PHire unavailable_end_date = DateTime.parse(unavailable_end_date.strftime("%Y-%m-%d " + unavailable_end_time.to_s + Time.zone.to_s)) rescue nil unavailable_weekdays = @property.weekdays.collect{|w| w.to_i} @recurring_events = self.where(:property_id => property_id, :recurring_end_date.gte => start_date) - if date_ony + if date_only @recurring_events = @recurring_events.where(:date.ne=>nil) end @recurring_events.each do |re| @@ -105,21 +108,23 @@ class PHire if interval != 0 @start_date = re.start_time recurring_end_date = re.recurring_end_date - end_date = [recurring_end_date,end_date].min + new_end_date = [recurring_end_date,end_date].min @end_date = re.end_time - while @start_date <= end_date do + while @start_date <= new_end_date do if unavailable && (unavailable_start_date <= @start_date) && (unavailable_end_date >= @end_date) && !((@start_date.strftime("%w").to_i .. @end_date.strftime("%w").to_i).to_a & unavailable_weekdays).empty? startt = DateTime.parse(@start_date.strftime("%Y-%m-%d " + unavailable_start_time + Time.zone.to_s)) endt = DateTime.parse(@end_date.strftime("%Y-%m-%d " + unavailable_end_time + Time.zone.to_s)) next if !((startt..endt) & (@start_date..@end_date)).blank? end - @recurring << re.as_json({:startt=>@start_date,:endt=>@end_date,:datet=>datet}) + if @start_date >= start_date + @recurring << re.as_json({:startt=>@start_date,:endt=>@end_date,:datet=>datet}) + end @start_date += interval @end_date += interval datet += interval if datet end end - end + end end @recurring end diff --git a/app/models/p_hire_field.rb b/app/models/p_hire_field.rb index de2be65..6ba34df 100644 --- a/app/models/p_hire_field.rb +++ b/app/models/p_hire_field.rb @@ -77,7 +77,18 @@ class PHireField def get_data self[panel] end - + def get_placeholder(locale=I18n.locale) + placeholder = self.get_data["placeholder"] rescue nil + if placeholder + if placeholder.respond_to?(:keys) + placeholder[locale.to_s] + else + placeholder + end + else + "" + end + end def typeA=(var) check_add_more_convert(var) check_cross_lang_convert(var,"typeA") diff --git a/app/models/p_hire_field_value.rb b/app/models/p_hire_field_value.rb index 917cf7c..12b99a3 100644 --- a/app/models/p_hire_field_value.rb +++ b/app/models/p_hire_field_value.rb @@ -74,14 +74,22 @@ class PHireFieldValue field_value = (field_value =~ /\A#{URI::regexp(['http', 'https'])}\z/) ? "#{field_value}" : field_value field_value = (field_value =~ /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/i) ? "#{field_value}" : field_value - - if !field_value.blank? - { - "key" => p_hire_field.key, - "title" => p_hire_field.title, - "value" => field_value, - "val" => field_value = self.value - } + if p_hire_field.markup.eql?("hint_text") + field_value = p_hire_field.get_placeholder rescue "" + { + "key" => p_hire_field.key, + "title" => p_hire_field.title, + "value" => field_value, + "val" => field_value, + "hint" => true + } + elsif !field_value.blank? + { + "key" => p_hire_field.key, + "title" => p_hire_field.title, + "value" => field_value, + "val" => field_value = self.value + } else { "key" => p_hire_field.key, diff --git a/app/models/property.rb b/app/models/property.rb index 03c978c..544fec0 100644 --- a/app/models/property.rb +++ b/app/models/property.rb @@ -4,6 +4,7 @@ class Property include OrbitTag::Taggable include OrbitCategory::Categorizable include Slug + 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 @@ -71,11 +72,40 @@ class Property "Friday", "Saturday" ] + CAlENDARTYPE = ["default","display","not_display"] before_create do max_position = self.class.max(:order_position) max_position = -1 if max_position.nil? self.order_position = max_position + 1 end + after_save do + self.change_day_setting_status + 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.last.calendar_type rescue 0) : (self.custom_calendar_type - 1)) + end def self.init_class_variables setting = PropertyHireSetting.last if setting @@ -189,6 +219,7 @@ class Property return true if self.weekdays.empty? && self.can_hire_before_months == 0 if self.can_hire_before_months != 0 return nil if (((stime - Time.now.to_datetime) * 1.day) > (self.can_hire_before_months).month) + available = true end startt = self.start_date.nil? ? stime : self.start_date endt = self.end_date.nil? ? etime : self.end_date @@ -198,18 +229,20 @@ class Property if !startt.nil? if !available 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 + available = true if common_dates.nil? + if !available + 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 + available = true if weekdays.blank? + 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? end - time_weekdays.uniq! - weekdays = weekdays & time_weekdays - return true if weekdays.blank? - 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? end if available if !recurring_end_date.blank? @@ -236,7 +269,7 @@ class Property end return available else - return false + return available end end end diff --git a/app/models/property_day_setting.rb b/app/models/property_day_setting.rb index f405ac4..f5ff768 100644 --- a/app/models/property_day_setting.rb +++ b/app/models/property_day_setting.rb @@ -1,6 +1,7 @@ class PropertyDaySetting include Mongoid::Document include Mongoid::Timestamps + field :enable, type: Boolean, default: true field :key field :day field :title diff --git a/app/models/property_hire_setting.rb b/app/models/property_hire_setting.rb index 782c196..b1be029 100644 --- a/app/models/property_hire_setting.rb +++ b/app/models/property_hire_setting.rb @@ -6,6 +6,8 @@ class PropertyHireSetting field :carousel_image_width, type: String, :default => "75%" field :disable_content_page, type: Boolean, :default => false field :disable_view_calendar_page, type: Boolean, :default => false + field :allow_no_logins_user, type: Boolean, :default => false + field :calendar_type, type: Integer, default: 0 # 0=> 顯示, 1=> 不顯示 def self.auto_approve_enabled? self.first.auto_approve rescue false end diff --git a/app/views/admin/property_hires/_form.html.erb b/app/views/admin/property_hires/_form.html.erb index cd68226..0ec200c 100644 --- a/app/views/admin/property_hires/_form.html.erb +++ b/app/views/admin/property_hires/_form.html.erb @@ -82,6 +82,7 @@