2013-01-07 09:04:09 +01:00
class Event < ActiveRecord :: Base
include ActiveRecord :: Transitions
2013-01-07 16:45:48 +01:00
has_paper_trail
2014-02-23 16:09:09 +02:00
2013-01-07 09:04:09 +01:00
acts_as_commentable
2014-06-25 14:58:33 +02:00
after_create :set_week
2014-06-24 12:14:53 +03:00
has_many :event_users , dependent : :destroy
has_many :users , through : :event_users
has_many :speakers , through : :event_users , source : :user
2014-07-17 16:48:27 +03:00
has_many :votes , dependent : :destroy
2014-06-24 12:14:53 +03:00
has_many :voters , through : :votes , source : :user
2014-08-05 18:23:42 +02:00
has_many :commercials , as : :commercialable , dependent : :destroy
2013-01-07 09:04:09 +01:00
belongs_to :event_type
2013-08-16 12:46:49 +03:00
2016-04-22 18:18:46 +03:00
has_many :events_registrations
has_many :registrations , through : :events_registrations
2013-01-07 09:04:09 +01:00
belongs_to :track
belongs_to :room
2014-02-23 16:09:09 +02:00
belongs_to :difficulty_level
2015-10-25 13:29:02 +02:00
belongs_to :program
2013-01-07 09:04:09 +01:00
2014-06-24 12:14:53 +03:00
accepts_nested_attributes_for :event_users , allow_destroy : true
2014-06-23 19:07:50 +03:00
accepts_nested_attributes_for :users
2015-04-16 18:34:41 +03:00
2013-01-07 09:04:09 +01:00
before_create :generate_guid
2013-01-16 08:22:20 +01:00
2013-01-07 09:04:09 +01:00
validate :abstract_limit
2014-12-18 13:38:40 +01:00
validate :before_end_of_conference , on : :create
2014-06-24 12:14:53 +03:00
validates :title , presence : true
validates :abstract , presence : true
2014-07-16 00:01:40 +02:00
validates :event_type , presence : true
2015-10-25 13:29:02 +02:00
validates :program , presence : true
2016-04-22 18:18:46 +03:00
validates :max_attendees , numericality : { only_integer : true , greater_than_or_equal_to : 1 , allow_nil : true }
validate :max_attendees_no_more_than_room_size
2016-06-06 12:31:57 +03:00
validate :max_attendees_no_less_than_existing_registrations
2013-01-07 09:04:09 +01:00
2014-04-23 15:45:55 +02:00
scope :confirmed , - > { where ( state : 'confirmed' ) }
2015-04-16 18:34:41 +03:00
scope :highlighted , - > { where ( is_highlight : true ) }
2013-07-16 18:42:22 +02:00
2014-06-24 12:14:53 +03:00
state_machine initial : :new do
2013-01-07 09:04:09 +01:00
state :new
state :withdrawn
state :unconfirmed
state :confirmed
state :canceled
state :rejected
2014-06-06 10:23:01 +02:00
event :restart do
transitions to : :new , from : [ :rejected , :withdrawn , :canceled ]
2013-01-07 09:04:09 +01:00
end
event :withdraw do
2014-06-06 10:23:01 +02:00
transitions to : :withdrawn , from : [ :new , :unconfirmed , :confirmed ]
2013-01-07 09:04:09 +01:00
end
event :accept do
2014-06-06 10:23:01 +02:00
transitions to : :unconfirmed , from : [ :new ] , on_transition : :process_acceptance
2013-01-07 09:04:09 +01:00
end
event :confirm do
2014-06-06 10:23:01 +02:00
transitions to : :confirmed , from : :unconfirmed , on_transition : :process_confirmation
2013-01-07 09:04:09 +01:00
end
event :cancel do
2014-06-06 10:23:01 +02:00
transitions to : :canceled , from : [ :unconfirmed , :confirmed ]
2013-01-07 09:04:09 +01:00
end
event :reject do
2014-06-06 10:23:01 +02:00
transitions to : :rejected , from : [ :new ] , on_transition : :process_rejection
2013-01-07 09:04:09 +01:00
end
end
2016-06-06 12:31:57 +03:00
def send_email_on_updated_max_attendees_automatically?
program . conference . email_settings . send_on_updated_max_attendees_automatically &&
program . conference . email_settings . updated_max_attendees_automatically_subject && program . conference . email_settings . updated_max_attendees_automatically_body
end
2016-04-22 18:18:46 +03:00
##
# Checkes if the event has a start_time and a room
# ====Returns
# * +true+ or +false+
def scheduled?
room && start_time ? true : false
end
def registration_possible?
2016-05-15 14:01:30 +03:00
return false unless require_registration && state == 'confirmed'
return true if max_attendees . nil?
2016-04-22 18:18:46 +03:00
registrations . count < max_attendees
end
2014-06-23 19:07:50 +03:00
def voted? ( event , user )
2014-06-24 12:14:53 +03:00
event . votes . where ( 'user_id = ?' , user ) . first
2013-08-16 12:46:49 +03:00
end
2014-06-23 19:07:50 +03:00
2013-08-16 12:46:49 +03:00
def average_rating
@total_rating = 0
2014-06-26 15:43:24 +03:00
votes . each do | vote |
2013-08-16 12:46:49 +03:00
@total_rating = @total_rating + vote . rating
end
2014-06-26 15:43:24 +03:00
@total = votes . size
2015-08-06 07:41:20 +03:00
@total_rating > 0 ? number_with_precision ( @total_rating / @total . to_f , precision : 2 , strip_insignificant_zeros : true ) : 0
2013-08-16 12:46:49 +03:00
end
2013-01-07 09:04:09 +01:00
def submitter
2014-06-26 15:43:24 +03:00
result = event_users . where ( event_role : 'submitter' ) . first
2013-01-07 09:04:09 +01:00
if ! result . nil?
2014-06-23 19:07:50 +03:00
result . user
2013-01-07 09:04:09 +01:00
else
2014-06-23 19:07:50 +03:00
user = nil
# Perhaps the event_users haven't been saved, if this is a new proposal
2014-06-26 15:43:24 +03:00
event_users . each do | u |
if u . event_role == 'submitter'
user = u . user
2013-02-06 20:17:54 +01:00
end
end
2014-06-23 19:07:50 +03:00
user
2013-01-07 09:04:09 +01:00
end
end
2014-02-23 16:09:09 +02:00
2013-01-11 15:00:54 +01:00
def as_json ( options )
json = super ( options )
2013-01-07 09:04:09 +01:00
2015-04-17 16:20:39 +02:00
json [ :room_guid ] = room . try ( :guid )
json [ :track_color ] = track . try ( :color ) || '#ffffff'
json [ :length ] = event_type . try ( :length ) || 25
2013-01-11 15:00:54 +01:00
json
end
2014-02-23 16:09:09 +02:00
2013-01-07 09:04:09 +01:00
def transition_possible? ( transition )
2014-06-26 15:43:24 +03:00
self . class . state_machine . events_for ( current_state ) . include? ( transition )
2013-01-07 09:04:09 +01:00
end
2014-06-06 10:23:01 +02:00
def process_confirmation
2015-10-25 13:29:02 +02:00
if program . conference . email_settings . send_on_confirmed_without_registration? &&
program . conference . email_settings . confirmed_without_registration_body &&
program . conference . email_settings . confirmed_without_registration_subject
2016-02-17 18:19:32 +01:00
if program . conference . registrations . where ( user_id : submitter . id ) . first . nil?
2016-04-20 18:59:24 +02:00
Mailbot . confirm_reminder_mail ( self ) . deliver_later
2013-02-12 19:17:19 +01:00
end
end
end
2014-02-23 16:09:09 +02:00
2013-01-07 09:04:09 +01:00
def process_acceptance ( options )
2015-10-25 13:29:02 +02:00
if program . conference . email_settings . send_on_accepted &&
program . conference . email_settings . accepted_body &&
program . conference . email_settings . accepted_subject &&
2014-07-23 13:42:03 +02:00
! options [ :send_mail ] . blank?
2016-04-20 18:59:24 +02:00
Mailbot . acceptance_mail ( self ) . deliver_later
2013-01-17 13:56:05 +01:00
end
end
2013-01-07 09:04:09 +01:00
2013-01-17 13:56:05 +01:00
def process_rejection ( options )
2015-10-25 13:29:02 +02:00
if program . conference . email_settings . send_on_rejected &&
program . conference . email_settings . rejected_body &&
program . conference . email_settings . rejected_subject &&
2014-07-23 13:42:03 +02:00
! options [ :send_mail ] . blank?
2016-04-20 18:59:24 +02:00
Mailbot . rejection_mail ( self ) . deliver_later
2013-01-17 13:56:05 +01:00
end
2013-01-07 09:04:09 +01:00
end
def abstract_word_count
2015-04-17 15:37:21 +02:00
abstract . to_s . split . size
2013-01-07 09:04:09 +01:00
end
2014-02-23 16:09:09 +02:00
2014-06-11 09:31:13 +02:00
def self . get_state_color ( state )
2015-04-17 16:33:30 +02:00
color = {
new : '#0000FF' , # blue
withdrawn : '#FF8000' , # orange
confirmed : '#00FF00' , # green
unconfirmed : '#FFFF00' , # yellow
rejected : '#FF0000' , # red
canceled : '#848484' # grey
} [ state . to_sym ]
color || '#00FFFF' # azure
2014-06-11 09:31:13 +02:00
end
2014-07-23 13:42:03 +02:00
def update_state ( transition , mail = false , subject = false , send_mail = false , send_mail_param )
alert = ''
if mail && send_mail_param && subject && send_mail
alert = 'Update Email Subject before Sending Mails'
end
begin
if mail
self . send ( transition ,
2014-07-30 23:32:29 +02:00
send_mail : send_mail_param )
2014-07-23 13:42:03 +02:00
else
self . send ( transition )
end
self . save
rescue Transitions :: InvalidTransition = > e
alert = " Update state failed. #{ e . message } "
end
alert
end
2014-08-28 15:21:05 +02:00
def speaker_names
2015-03-09 15:31:06 +01:00
result = Set . new
2014-08-28 15:21:05 +02:00
speakers . each do | speaker |
2015-03-09 15:31:06 +01:00
result . add ( speaker . name )
2014-08-28 15:21:05 +02:00
end
2015-03-09 15:31:06 +01:00
result . to_a . to_sentence
2014-08-28 15:21:05 +02:00
end
2015-04-16 18:34:41 +03:00
##
#
# Returns +Hash+
def progress_status
{
2015-10-25 13:29:02 +02:00
registered : self . program . conference . user_registered? ( self . submitter ) ,
2015-04-16 18:34:41 +03:00
commercials : self . commercials . any? ,
biography : ! self . submitter . biography . blank? ,
subtitle : ! self . subtitle . blank? ,
2016-03-18 01:59:05 +05:30
track : ( ! self . track . blank? unless self . program . tracks . empty? ) ,
2015-04-16 18:34:41 +03:00
difficulty_level : ! self . difficulty_level . blank? ,
title : true ,
abstract : true
} . with_indifferent_access
end
##
# Returns the progress of the proposal's set up
#
# ====Returns
2015-05-16 15:17:20 +02:00
# * +String+ -> Progress in Percent
2015-04-16 18:34:41 +03:00
def calculate_progress
result = self . progress_status
2016-03-18 01:59:05 +05:30
( 100 * result . values . count ( true ) / result . values . compact . count ) . to_s
2015-04-16 18:34:41 +03:00
end
2013-01-07 09:04:09 +01:00
private
2016-04-22 18:18:46 +03:00
##
# Do not allow, for the event, more attendees than the size of the room
def max_attendees_no_more_than_room_size
return unless room && max_attendees_changed?
errors . add ( :max_attendees , " cannot be more than the room's capacity ( #{ room . size } ) " ) if max_attendees && ( max_attendees > room . size )
end
2016-06-06 12:31:57 +03:00
##
# The value of max_attendees for an event cannot less than the number of existing registrations to that event
def max_attendees_no_less_than_existing_registrations
return unless max_attendees && max_attendees_changed?
errors . add ( :max_attendees , 'cannot be less than existing registrations. You first need to unregister people, if you want to reduce this value.' ) if max_attendees < self . registrations . count
end
2013-01-07 09:04:09 +01:00
def abstract_limit
2014-07-16 00:01:40 +02:00
# If we don't have an event type, there is no need to count anything
2016-02-26 15:19:23 +02:00
return unless event_type && abstract
2014-06-26 15:43:24 +03:00
len = abstract . split . size
2014-07-16 00:01:40 +02:00
max_words = event_type . maximum_abstract_length
min_words = event_type . minimum_abstract_length
2013-01-31 14:38:58 +01:00
2014-07-16 00:01:40 +02:00
errors . add ( :abstract , " cannot have less than #{ min_words } words " ) if len < min_words
errors . add ( :abstract , " cannot have more than #{ max_words } words " ) if len > max_words
2013-01-07 09:04:09 +01:00
end
2014-07-21 14:27:32 +02:00
# TODO: create a module to be mixed into model to perform same operation
# venue.rb has same functionality which can be shared
# TODO: rename guid to UUID as guid is specifically Microsoft term
2013-01-07 09:04:09 +01:00
def generate_guid
2014-07-21 14:27:32 +02:00
loop do
@guid = SecureRandom . urlsafe_base64
break if ! self . class . where ( guid : guid ) . any?
end
self . guid = @guid
2013-01-07 09:04:09 +01:00
end
2014-06-25 14:58:33 +02:00
def set_week
self . week = created_at . strftime ( '%W' )
save!
end
2014-07-07 14:58:53 +02:00
def before_end_of_conference
errors .
2015-10-25 13:29:02 +02:00
add ( :created_at , " can't be after the conference end date! " ) if program . conference && program . conference . end_date &&
( Date . today > program . conference . end_date )
2014-07-07 14:58:53 +02:00
end
2013-05-07 17:00:26 +02:00
end