Implements targets and campaigns for conference
This commit is contained in:
parent
678fe38a25
commit
857ac43e74
40 changed files with 1086 additions and 44 deletions
10
app/models/ahoy/event.rb
Normal file
10
app/models/ahoy/event.rb
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
module Ahoy
|
||||
class Event < ActiveRecord::Base
|
||||
self.table_name = "ahoy_events"
|
||||
|
||||
belongs_to :visit
|
||||
belongs_to :user
|
||||
|
||||
serialize :properties, JSON
|
||||
end
|
||||
end
|
||||
77
app/models/campaign.rb
Normal file
77
app/models/campaign.rb
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
class Campaign < ActiveRecord::Base
|
||||
attr_accessible :name, :utm_source, :utm_medium, :utm_term,
|
||||
:utm_content, :utm_campaign, :target_ids
|
||||
|
||||
validates :name, :utm_campaign, presence: true
|
||||
|
||||
has_many :targets
|
||||
belongs_to :conference
|
||||
|
||||
##
|
||||
# Returns the utm parameters formatted as url.
|
||||
#
|
||||
# ====Returns
|
||||
# * +String+ -> url parameters e.g. ?utm_source=facebook
|
||||
def url_parameters
|
||||
kv = []
|
||||
get_parameters.each_pair do |k, v|
|
||||
kv += ["#{k}=#{v}"]
|
||||
end
|
||||
'?' + kv.join('&') unless kv.empty?
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the counted visits generated by this campaign.
|
||||
#
|
||||
# ====Returns
|
||||
# * +Fixnum+ -> visits
|
||||
def visits_count
|
||||
Visit.where(get_parameters).where('started_at > ?', created_at).count
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the counted registrations generated by this campaign.
|
||||
#
|
||||
# ====Returns
|
||||
# * +Fixnum+ -> visits
|
||||
def registrations_count
|
||||
events_by_name('Registered')
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the counted event submissions generated by this campaign.
|
||||
#
|
||||
# ====Returns
|
||||
# * +Fixnum+ -> visits
|
||||
def submissions_count
|
||||
events_by_name('Event submission')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
##
|
||||
# Helper method for submissions and registrations.
|
||||
#
|
||||
# ====Returns
|
||||
# * +Fixnum+ -> registrations / submissions
|
||||
def events_by_name(event_name)
|
||||
parameters = get_parameters
|
||||
parameters['ahoy_events.name'] = event_name
|
||||
Visit.joins(:ahoy_events).where(parameters).where('started_at > ?', created_at).count
|
||||
end
|
||||
|
||||
##
|
||||
# Helper method to get the parameters for queries.
|
||||
#
|
||||
# ====Returns
|
||||
# * +Hash+ -> parameter => value
|
||||
def get_parameters
|
||||
conditions = {}
|
||||
conditions[:utm_source] = self[:utm_source] unless self[:utm_source].blank?
|
||||
conditions[:utm_medium] = self[:utm_medium] unless self[:utm_medium].blank?
|
||||
conditions[:utm_term] = self[:utm_term] unless self[:utm_term].blank?
|
||||
conditions[:utm_content] = self[:utm_content] unless self[:utm_content].blank?
|
||||
conditions[:utm_campaign] = self[:utm_campaign] unless self[:utm_campaign].blank?
|
||||
conditions
|
||||
end
|
||||
end
|
||||
|
|
@ -21,7 +21,8 @@ class Conference < ActiveRecord::Base
|
|||
:include_tickets_in_splash, :include_social_media_in_splash,
|
||||
:include_program_in_splash, :make_conference_public,
|
||||
:photos_attributes, :banner_photo,
|
||||
:include_banner_in_splash
|
||||
:include_banner_in_splash,
|
||||
:targets, :targets_attributes, :campaigns, :campaigns_attributes
|
||||
|
||||
has_paper_trail
|
||||
|
||||
|
|
@ -45,6 +46,8 @@ class Conference < ActiveRecord::Base
|
|||
has_many :sponsorship_levels, dependent: :destroy
|
||||
has_many :sponsors, dependent: :destroy
|
||||
has_many :photos, dependent: :destroy
|
||||
has_many :targets, dependent: :destroy
|
||||
has_many :campaigns, dependent: :destroy
|
||||
belongs_to :venue
|
||||
|
||||
accepts_nested_attributes_for :rooms, :reject_if => proc {|r| r["name"].blank?}, :allow_destroy => true
|
||||
|
|
@ -62,6 +65,8 @@ class Conference < ActiveRecord::Base
|
|||
accepts_nested_attributes_for :vdays, :allow_destroy => true
|
||||
accepts_nested_attributes_for :vpositions, :allow_destroy => true
|
||||
accepts_nested_attributes_for :photos, allow_destroy: true
|
||||
accepts_nested_attributes_for :targets, allow_destroy: true
|
||||
accepts_nested_attributes_for :campaigns, allow_destroy: true
|
||||
|
||||
has_attached_file :logo,
|
||||
styles: { thumb: '100x100>', large: '300x300>' }
|
||||
|
|
@ -457,6 +462,35 @@ class Conference < ActiveRecord::Base
|
|||
result
|
||||
end
|
||||
|
||||
##
|
||||
# A map with all conference targets with progress in percent of a certain unit.
|
||||
#
|
||||
# ====Returns
|
||||
# * +Map+ -> target => progress
|
||||
def get_targets(target_unit)
|
||||
conference_target = targets.where('unit = ?', target_unit)
|
||||
result = {}
|
||||
conference_target.each do |target|
|
||||
result[target.to_s] = target.get_progress
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
##
|
||||
# A map with all conference campaigns associated with targets.
|
||||
#
|
||||
# ====Returns
|
||||
# * +Map+ -> campaign => {actual, target, progress}
|
||||
def get_campaigns
|
||||
result = {}
|
||||
campaigns.each do |campaign|
|
||||
campaign.targets.each do |target|
|
||||
result["#{target} from #{campaign.name}"] = target.get_campaign
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
##
|
||||
|
|
@ -655,12 +689,12 @@ class Conference < ActiveRecord::Base
|
|||
#
|
||||
# ====Returns
|
||||
# * +hash+ -> person: submissions
|
||||
def self.calculate_person_submission_hash(submitter, counter)
|
||||
def self.calculate_person_submission_hash(submitters, counter)
|
||||
result = ActiveSupport::OrderedHash.new
|
||||
counter.each do |key, value|
|
||||
submitter = submitter.find_by_id(key)
|
||||
submitter = submitters.where(person_id: key).first
|
||||
if submitter
|
||||
result[submitter] = value
|
||||
result[submitter.person] = value
|
||||
end
|
||||
end
|
||||
result
|
||||
|
|
|
|||
79
app/models/target.rb
Normal file
79
app/models/target.rb
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
class Target < ActiveRecord::Base
|
||||
include ActionView::Helpers::TextHelper
|
||||
|
||||
attr_accessible :due_date, :target_count, :unit
|
||||
|
||||
default_scope { order('due_date ASC') }
|
||||
|
||||
def self.units
|
||||
{
|
||||
registrations: 'Registration',
|
||||
submissions: 'Submission',
|
||||
program_minutes: 'Program minute'
|
||||
}
|
||||
end
|
||||
|
||||
validates :due_date, :target_count, :unit, presence: true
|
||||
validates :target_count,
|
||||
allow_nil: false,
|
||||
numericality: { only_integer: true, greater_than: 0 }
|
||||
validates :unit, allow_nil: false, inclusion: { in: Target.units.values }
|
||||
|
||||
belongs_to :conference
|
||||
belongs_to :campaign
|
||||
|
||||
##
|
||||
# Returns the actual progress of the target in percent.
|
||||
#
|
||||
# ====Returns
|
||||
# * +String+ -> progress in percent
|
||||
def get_progress
|
||||
numerator = 0
|
||||
if unit == Target.units[:submissions]
|
||||
numerator = conference.events.where('created_at < ?', due_date).count
|
||||
elsif unit == Target.units[:registrations]
|
||||
numerator = conference.registrations.where('created_at < ?', due_date).count
|
||||
elsif unit == Target.units[:program_minutes]
|
||||
numerator = conference.current_program_hours
|
||||
end
|
||||
(numerator / target_count.to_f * 100).round(0).to_s
|
||||
end
|
||||
|
||||
##
|
||||
# Returns a hash with values of the corresponding campaign.
|
||||
#
|
||||
# ====Returns
|
||||
# * +Hash+ -> target_name, campaign_name, value, unit, created_at, progress, days_left
|
||||
def get_campaign
|
||||
numerator = 0
|
||||
if unit == Target.units[:submissions]
|
||||
numerator = campaign.submissions_count
|
||||
elsif unit == Target.units[:registrations]
|
||||
numerator = campaign.registrations_count
|
||||
elsif unit == Target.units[:program_minutes]
|
||||
numerator = campaign.current_program_hours
|
||||
end
|
||||
|
||||
progress = (numerator / target_count.to_f * 100).round(0).to_s
|
||||
result = {
|
||||
'target_name' => to_s,
|
||||
'campaign_name' => campaign.name,
|
||||
'value' => numerator,
|
||||
'unit' => unit,
|
||||
'created_at' => created_at,
|
||||
'progress' => progress,
|
||||
'days_left' => days_left,
|
||||
}
|
||||
result
|
||||
end
|
||||
|
||||
def to_s
|
||||
"#{pluralize(target_count, unit)} by #{due_date}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def days_left
|
||||
(due_date - Date.today).to_i
|
||||
end
|
||||
end
|
||||
4
app/models/visit.rb
Normal file
4
app/models/visit.rb
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
class Visit < ActiveRecord::Base
|
||||
has_many :ahoy_events, class_name: "Ahoy::Event"
|
||||
belongs_to :user
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue