diff --git a/app/controllers/admin/stats_controller.rb b/app/controllers/admin/stats_controller.rb index 4de35dc6..d0820a1d 100644 --- a/app/controllers/admin/stats_controller.rb +++ b/app/controllers/admin/stats_controller.rb @@ -3,9 +3,8 @@ class Admin::StatsController < ApplicationController def index @registrations = @conference.registrations.includes(:person).order("registrations.created_at ASC") - - @attendees = @conference.registrations.where("attended = ?", true).count @registered = @conference.registrations.count + @attendees = @conference.registrations.where("attended = ?", true).count @pre_registered = @conference.registrations.where("created_at < ?", @conference.start_date).count @pre_registered_attended = @conference.registrations.where("created_at < ? AND attended = ?", @conference.start_date, true).count @@ -16,34 +15,118 @@ class Admin::StatsController < ApplicationController @handicapped_access_attended = @conference.registrations.where(handicapped_access_required: true) @handicapped_access_attended = @handicapped_access_attended.where(attended: true).count @suggested_hotel_stay = @conference.registrations.where("using_affiliated_lodging = ?", true).count + + @events = @conference.events +#Events charts + @machine_states = [['confirmed'], ['cancelled'], ['rejected'], ['withdrawn'], ['new', 'review'], ['unconfirmed', 'accepted']] + #Types distribution per state + @type_state = {} + @machine_states.each do |state| + @type_state[state[0]] = var_state_func(@conference.event_types, "event_type", state) + end + #Tracks distribution per state + @no_track_all = @events.where(track_id: nil) + @no_track_new = @events.where(track_id: nil).where(state: ['new', 'review']) + @no_track_unconfirmed = @events.where(track_id: nil).where(state: "unconfirmed") + @no_track_confirmed = @events.where(track_id: nil).where(state: "confirmed") + @track_state = {} + @machine_states.each do |state| + @track_state[state[0]] = var_state_func(@conference.tracks, "track", state) + end + + #Events_time chart + if @events.count > 0 + start_date = @events.minimum("created_at").strftime("%Y-%m-%d") + end_date = @events.maximum("created_at").strftime("%Y-%m-%d") + if start_date != nil && end_date != nil + @events_time = var_time(start_date, end_date, @events, "created_at") + end + end + + #Code for the table in events + @mystates = [] + @mytypes = [] + @eventstats = {} + statelength = 0 + @totallength = 0 + #Get totals per state + @events.state_machine.states.map.each do |mystate| + length = 0 + events_mystate= @events.where("state" => mystate.name) + if events_mystate.count > 0 + @mystates << mystate + events_mystate.each do |myevent| + length += myevent.event_type.length + end + @eventstats["#{mystate.name}"] = {"count" => events_mystate.count, "length" => length} + end + end + + @conference.event_types.each do |mytype| + events_mytype = @events.where("event_type_id" => mytype.id) + if events_mytype.count > 0 + @mytypes << mytype + end + end + @mytypes.each do |mytype| + @mystates.each do |mystate| + events_mytype = @events.where("event_type_id" => mytype.id) + events_mytype_mystate= events_mytype.where("state" => mystate.name) + typelength = 0 + if events_mytype_mystate.count > 0 + events_mytype_mystate.each do |myevent| + typelength += myevent.event_type.length + @totallength += myevent.event_type.length + end + @eventstats[mytype.title] = {"count" => events_mytype.count, "length" => events_mytype.count * mytype.length} if @eventstats[mytype.title] == nil + tmp = {"#{mystate.name}" => {"type_state_count" => events_mytype_mystate.count, "type_state_length" => typelength}} + @eventstats[mytype.title].merge!(tmp) + end + end + end + @eventstats["totallength"] = @totallength + +#SPEAKERS stats @speakers = Person.joins(:events).where("events.conference_id = ? AND events.state LIKE ?", @conference.id, 'confirmed').uniq @speaker_fields_person = %w[name email affiliation] - @speaker_fields_reg = %w[other_needs diet arrival departure] - + @speaker_fields_reg = %w[arrival departure] +#TICKETS stats @supporter_levels = @conference.supporter_levels @tickets = @conference.registrations.joins(:supporter_registration => :supporter_level) @tickets = @tickets.where("supporter_levels.title NOT LIKE ? ", "%Free%") - @mydays = [] - @mytickets = [] + @tickets_time = [] - if @conference.registration_start_date and @conference.end_date - (@conference.registration_start_date..@conference.end_date).each do |day| - day_reg_count = @registrations.where("created_at LIKE '%#{day}%' ").count - day_ticket_count = @tickets.where("supporter_registrations.created_at LIKE '%#{day}%' ").count - if day_reg_count != 0 - @mydays << {"status" => "#{day}", "value" => day_reg_count} - end - @conference.supporter_levels.each do |level| - day_ticket_count = @tickets.where("supporter_registrations.created_at LIKE ? AND supporter_levels.title LIKE ?", "%#{day}%", "%#{level.title}%").count - if day_ticket_count !=0 - @mytickets << {"status" => "#{day}", "ticket" => "#{level}", "value" => day_ticket_count} - end + if @conference.registration_start_date and @conference.end_date and @registered > 0 and @supporter_levels + start_date = @conference.registration_start_date + end_date = @conference.end_date + levels = []; + @conference.supporter_levels.each do |level| + @tickets_time << {"key" => level.title, "values" => []} + levels << ["#{level.title}"] + end + + (start_date..end_date).each do |day| + if @tickets.where("supporter_registrations.created_at LIKE ?", "%#{day}%").where("supporter_levels.title" => levels).count != 0 + @conference.supporter_levels.each do |level| + + day_ticket_count = @tickets.where("supporter_registrations.created_at LIKE ? AND supporter_levels.title LIKE ?", "%#{day}%", "%#{level.title}%").count + + index = @tickets_time.index {|v| v["key"] == "#{level.title}"} + @tickets_time[index]["values"] << {"label" => "#{day}", "value" => day_ticket_count} + end end end end - + @tickets_distribution = [] + @tickets_time.each do |ticket| + value = ticket["values"].map{|x| x["value"]}.sum + percent = (value.to_f / @tickets.count * 100).round(2) + @tickets_distribution << {"status" => ticket["key"], "value" => value, "percent" => percent} + end + +#OTHER_INFO chart / To be 'Questions' @other_info = [ {"status" => "with partner (registered)", "value" => @registered_with_partner}, {"status" => "with partner (attended)", "value" => @attended_with_partner}, @@ -52,8 +135,58 @@ class Admin::StatsController < ApplicationController {"status" => "stay at suggested hotel", "value" => @suggested_hotel_stay} ] +# REGISTRATIONS, registered_time + if @conference.registration_start_date and @conference.end_date and @registered > 0 + start_date = @conference.registration_start_date + end_date = @conference.end_date + @registered_time = var_time(start_date, end_date, @registrations, "created_at") + end + + respond_to do |format| + format.html + format.json { render :json => @tickets_time.to_json } + end end - +#FUNCTIONS + def var_time(start_date, end_date, var, field) + result = [] + (start_date..end_date).each do |day| + day_var_count = var.where("#{field} LIKE ?", "%#{day}%").count + if day_var_count !=0 + result << {"status" => "#{day}", "value" => day_var_count} + end + end + return result + end + + def var_state_func(vars, field, mystate) + result = [] + + for myvar in vars do + #Find events per track and state + value = @conference.events.where("#{field}_id" => myvar.id).where(state: mystate).count + #Find all events in that state + total = @conference.events.where(state: mystate).count + status = "#{myvar.name}" + + if value != 0 + percent = (value.to_f / total * 100).round(2) + result << {"status" => status, "value" => value, "percent" => percent} + else + percent = 0 + end + end + #Get no of events for which the field is not set (Needed so that the pie shows half piece for 50%) + sum = result.inject(0) {|sum, hash| sum + hash["value"]} + value = total - sum if total and sum + if sum !=0 && value !=0 + percent = (value.to_f / total * 100).round(2) + result << {"status" => "no #{field} set", "value" => value, "percent" => percent } + end + + return result + end + def speaker_reg(speaker) speaker.registrations.where("conference_id = ? AND person_id = ?", @conference.id, speaker.id).first end @@ -74,4 +207,4 @@ class Admin::StatsController < ApplicationController helper_method :speaker_diet helper_method :diet_count helper_method :social_event_count -end +end \ No newline at end of file diff --git a/app/models/event_type.rb b/app/models/event_type.rb index 9bf7d734..5d375084 100644 --- a/app/models/event_type.rb +++ b/app/models/event_type.rb @@ -4,4 +4,6 @@ class EventType < ActiveRecord::Base belongs_to :conference validates :length, :numericality => {:greater_than => 0} + + alias_attribute :name, :title end diff --git a/app/views/admin/stats/_events.html.haml b/app/views/admin/stats/_events.html.haml new file mode 100644 index 00000000..04c07c4b --- /dev/null +++ b/app/views/admin/stats/_events.html.haml @@ -0,0 +1,41 @@ +-if @events.count > 0 + %h2{:style => "text-align: center"} + = "Events (#{@events.count})" + + .row-fluid + %h3 + %u Types per event state + - if !@conference.event_types.empty? + = render :partial => "events_types" + - else + %h4 + %i There are no tracks defined for this conference! + + .row-fluid + %h3 + %u Tracks per event state + - if @no_track_all.count > 0 + %i= " (#{pluralize(@no_track_all.count, 'event')} not assigned to a track)" + - if !@conference.tracks.empty? + = render :partial => "events_tracks" + - else + %h4 + %i There are no tracks defined for this conference! + + .row-fluid + .span12 + %h3 Proposal Submissions over time + .row-fluid + .span12#events_time + = render :partial => "events_time" + + .row-fluid + .span12 + %br + %h3 Overview of all events + .row-fluid + .span12#events_table + = render :partial => "events_table" + +- else + %h5 There are no submitted events yet. diff --git a/app/views/admin/stats/_events_table.html.haml b/app/views/admin/stats/_events_table.html.haml new file mode 100644 index 00000000..0477f18a --- /dev/null +++ b/app/views/admin/stats/_events_table.html.haml @@ -0,0 +1,34 @@ +%table.table.table-bordered.table-striped + %thead + %th + - @mystates.each do |state| + %th{:colspan => 2, :style => "text-align:center"} + State "#{state.name}" + %th{:colspan => 2, :style => "text-align:center"} + Total + %br + No & Time + + %tr + %td + %b Total + - @mystates.each do |mystate| + %td + %b + = @eventstats["#{mystate.name}"]["count"] + %td + %b + #{@eventstats["#{mystate.name}"]["length"] / 60} h #{@eventstats["#{mystate.name}"]["length"] - @eventstats["#{mystate.name}"]["length"] / 60 * 60} m + %td + %b= @events.count + %td + %b= show_time(@eventstats["totallength"]) + + - @mytypes.each do |mytype| + %tr + %td= "#{mytype.title} (#{show_time(mytype.length)})" + - @mystates.each do |mystate| + %td= @eventstats["#{mytype.title}"]["#{mystate.name}"]["type_state_count"] unless @eventstats["#{mytype.title}"]["#{mystate.name}"] == nil + %td= show_time(@eventstats["#{mytype.title}"]["#{mystate.name}"]["type_state_length"]) unless @eventstats["#{mytype.title}"]["#{mystate.name}"] == nil + %td= @eventstats["#{mytype.title}"]["count"] + %td= show_time(@eventstats["#{mytype.title}"]["length"]) diff --git a/app/views/admin/stats/_events_time.html b/app/views/admin/stats/_events_time.html new file mode 100644 index 00000000..25f18d6b --- /dev/null +++ b/app/views/admin/stats/_events_time.html @@ -0,0 +1,71 @@ + \ No newline at end of file diff --git a/app/views/admin/stats/_events_tracks.html.haml b/app/views/admin/stats/_events_tracks.html.haml new file mode 100644 index 00000000..6ecef217 --- /dev/null +++ b/app/views/admin/stats/_events_tracks.html.haml @@ -0,0 +1,35 @@ +.row-fluid + - if !@track_state['new'].empty? + .span4 + %h4 New Submissions + - if @no_track_new.count > 0 + %h5= "#{pluralize(@no_track_new.count, 'event')} not assigned to a track" + - else + %h5 + .row-fluid + .span12#events_tracks_new + = render :partial => "events_tracks_new" + + - if !@track_state['unconfirmed'].empty? + .span4 + %h4 Accepted (Unconfirmed) + - if @no_track_unconfirmed.count > 0 + %h5= "#{pluralize(@no_track_unconfirmed.count, 'event')} not assigned to a track" + - else + %h5 All events assigned to track! + + .row-fluid + .span12#events_tracks_unconfirmed + = render :partial => "events_tracks_unconfirmed" + + - if !@track_state['confirmed'].empty? + .span4 + %h4 Accepted (Confirmed) + - if @no_track_confirmed.count > 0 + %h5= "#{pluralize(@no_track_confirmed.count, 'event')} not assigned to a track" + - else + %h5 All events assigned to track! + + .row-fluid + .span12#events_tracks_confirmed + = render :partial => "events_tracks_confirmed" diff --git a/app/views/admin/stats/_events_tracks_confirmed.html b/app/views/admin/stats/_events_tracks_confirmed.html new file mode 100644 index 00000000..d031ed30 --- /dev/null +++ b/app/views/admin/stats/_events_tracks_confirmed.html @@ -0,0 +1,79 @@ + + + \ No newline at end of file diff --git a/app/views/admin/stats/_events_tracks_new.html b/app/views/admin/stats/_events_tracks_new.html new file mode 100644 index 00000000..d8d4e81c --- /dev/null +++ b/app/views/admin/stats/_events_tracks_new.html @@ -0,0 +1,79 @@ + + + \ No newline at end of file diff --git a/app/views/admin/stats/_events_tracks_unconfirmed.html b/app/views/admin/stats/_events_tracks_unconfirmed.html new file mode 100644 index 00000000..1af6b1ad --- /dev/null +++ b/app/views/admin/stats/_events_tracks_unconfirmed.html @@ -0,0 +1,79 @@ + + + \ No newline at end of file diff --git a/app/views/admin/stats/_events_types.html.haml b/app/views/admin/stats/_events_types.html.haml new file mode 100644 index 00000000..3d6ac9fd --- /dev/null +++ b/app/views/admin/stats/_events_types.html.haml @@ -0,0 +1,19 @@ +.row-fluid + - if !@type_state['new'].empty? + .span4 + %h4 New Submissions: #{@type_state['new'].map{|x| x["value"]}.sum} + .row-fluid + .span12#events_types_new + = render :partial => "events_types_new" + - if !@type_state['unconfirmed'].empty? + .span4 + %h4 Accepted (Unconfirmed): #{@type_state['unconfirmed'].map{|x| x["value"]}.sum} + .row-fluid + .span12#events_types_unconfirmed + = render :partial => "events_types_unconfirmed" + - if !@type_state['confirmed'].empty? + .span4 + %h4 Accepted (Confirmed): #{@type_state['confirmed'].map{|x| x["value"]}.sum} + .row-fluid + .span12#events_types_confirmed + = render :partial => "events_types_confirmed" \ No newline at end of file diff --git a/app/views/admin/stats/_events_types_confirmed.html b/app/views/admin/stats/_events_types_confirmed.html new file mode 100644 index 00000000..247e8a14 --- /dev/null +++ b/app/views/admin/stats/_events_types_confirmed.html @@ -0,0 +1,78 @@ + + + \ No newline at end of file diff --git a/app/views/admin/stats/_events_types_new.html b/app/views/admin/stats/_events_types_new.html new file mode 100644 index 00000000..fc560371 --- /dev/null +++ b/app/views/admin/stats/_events_types_new.html @@ -0,0 +1,78 @@ + + + \ No newline at end of file diff --git a/app/views/admin/stats/_events_types_unconfirmed.html b/app/views/admin/stats/_events_types_unconfirmed.html new file mode 100644 index 00000000..4335eab0 --- /dev/null +++ b/app/views/admin/stats/_events_types_unconfirmed.html @@ -0,0 +1,78 @@ + + + \ No newline at end of file diff --git a/app/views/admin/stats/_registered_time.html b/app/views/admin/stats/_registered_time.html index fe1ecc48..e3de08e0 100644 --- a/app/views/admin/stats/_registered_time.html +++ b/app/views/admin/stats/_registered_time.html @@ -1,7 +1,7 @@ \ No newline at end of file diff --git a/app/views/admin/stats/_tickets.html.haml b/app/views/admin/stats/_tickets.html.haml index 03c2e99b..f9e25c39 100644 --- a/app/views/admin/stats/_tickets.html.haml +++ b/app/views/admin/stats/_tickets.html.haml @@ -1,5 +1,22 @@ -- if @tickets - %h2 - = "Non-Free Tickets(#{@tickets.count})" -.span4#tickets_time -= render :partial => "tickets_time" \ No newline at end of file +- if @tickets.length > 0 + .row-fluid + .span12 + %h2 + = "Non-Free Tickets (#{@tickets.count})" + .row-fluid + .span4 + %h4 Ticket distribution + .row-fluid + .span12#tickets_distribution + = render :partial => "tickets_distribution" + .row-fluid + .span10 + %h4 Ticket sales over time + .row-fluid + .span12#tickets_time + = render :partial => "tickets_time" +- else + - if @conference.use_supporter_levels + %h5 No tickets have been bought yet. + - else + %h5 There are no tickets set for this conference. \ No newline at end of file diff --git a/app/views/admin/stats/_tickets_distribution.html b/app/views/admin/stats/_tickets_distribution.html new file mode 100644 index 00000000..b12163d1 --- /dev/null +++ b/app/views/admin/stats/_tickets_distribution.html @@ -0,0 +1,79 @@ + + + \ No newline at end of file diff --git a/app/views/admin/stats/_tickets_time.html b/app/views/admin/stats/_tickets_time.html index a984443b..6e0b8d44 100644 --- a/app/views/admin/stats/_tickets_time.html +++ b/app/views/admin/stats/_tickets_time.html @@ -1,86 +1 @@ - \ No newline at end of file +(Not yet implemented) \ No newline at end of file diff --git a/app/views/admin/stats/index.html.haml b/app/views/admin/stats/index.html.haml index b001a953..4d56d86f 100644 --- a/app/views/admin/stats/index.html.haml +++ b/app/views/admin/stats/index.html.haml @@ -3,6 +3,8 @@ %ul.nav.nav-tabs#myTab %li.active %a{:href=>"#registrations", "data-toggle"=>"tab"} Registrations + %li + %a{:href=>"#events", "data-toggle"=>"tab"} Events %li %a{:href=>"#speakers", "data-toggle"=>"tab"} Speakers %li @@ -11,6 +13,8 @@ .tab-content .tab-pane.active#registrations = render :partial => 'registrations' + .tab-pane#events + = render :partial => 'events' .tab-pane#speakers = render :partial => 'speakers' .tab-pane#tickets