osem-fcy/app/models/track.rb
AEtherC0r3 d9faffc96a Implement track request acceptance
Allow track submitter to request specific dates
Redirect to Tracks#edit if a track doesn't have a room or start/end date
before accepting it

Don't allow the submitter or the track organizers to edit the request
after it has been accepted or confirmed

Restrict track selection in proposals and move track selection from
Proposals form to events helper

Mark cfp_active of the tracks table as not null and fill in true if nil
2017-08-11 16:25:21 +03:00

207 lines
6.2 KiB
Ruby

class Track < ActiveRecord::Base
include ActiveRecord::Transitions
include RevisionCount
resourcify :roles, dependent: :delete_all
belongs_to :program
belongs_to :submitter, class_name: 'User'
belongs_to :room
has_many :events, dependent: :nullify
has_paper_trail only: [:name, :description, :color], meta: { conference_id: :conference_id }
before_create :generate_guid
validates :name, presence: true
validates :color, format: /\A#[0-9A-F]{6}\z/
validates :short_name,
presence: true,
format: /\A[a-zA-Z0-9_-]*\z/,
uniqueness: {
scope: :program
}
validates :state,
presence: true,
inclusion: { in: %w(new to_accept accepted confirmed to_reject rejected canceled withdrawn) }
validates :cfp_active, inclusion: { in: [true, false] }
validates :start_date, presence: true, if: :self_organized_and_accepted_or_confirmed?
validates :end_date, presence: true, if: :self_organized_and_accepted_or_confirmed?
validates :room, presence: true, if: :self_organized_and_accepted_or_confirmed?
validate :valid_dates
validate :valid_room, if: :self_organized_and_accepted_or_confirmed?
before_validation :capitalize_color
state_machine initial: :pending do
state :new
state :to_accept
state :accepted
state :confirmed
state :to_reject
state :rejected
state :canceled
state :withdrawn
event :restart do
transitions to: :new, from: [:rejected, :withdrawn, :canceled]
end
event :to_accept do
transitions to: :to_accept, from: [:new]
end
event :accept do
transitions to: :accepted, from: [:new, :to_accept], on_transition: :create_organizer_role
end
event :confirm do
transitions to: :confirmed, from: [:accepted], on_transition: :assign_role_to_submitter
end
event :to_reject do
transitions to: :to_reject, from: [:new]
end
event :reject do
transitions to: :rejected, from: [:new, :to_reject]
end
event :cancel do
transitions to: :canceled, from: [:to_accept, :to_reject, :accepted, :confirmed], on_transition: :revoke_role_and_cleanup
end
event :withdraw do
transitions to: :withdrawn, from: [:new, :to_accept, :to_reject, :accepted, :confirmed], on_transition: :revoke_role_and_cleanup
end
end
def conference
program.conference
end
##
# Checks if the track is self-organized
# ====Returns
# * +true+ -> If the track has a submitter
# * +false+ -> if the track doesn't have a submitter
def self_organized?
return true if submitter
false
end
def to_param
short_name
end
def transition_possible?(transition)
self.class.state_machine.events_for(current_state).include?(transition)
end
# Gives the role of the track_organizer to the submitter
def assign_role_to_submitter
submitter.add_role 'track_organizer', self
end
# Revokes the track organizer role and removes the track from events that have it set
def revoke_role_and_cleanup
role = Role.find_by(name: 'track_organizer', resource: self)
if role
role.users.each do |user|
user.remove_role 'track_organizer', self
end
end
events.each do |event|
event.track = nil
event.save!
end
end
##
# Checks if the track is accepted
# ====Returns
# * +true+ -> If the track's state is 'accepted'
# * +false+ -> If the track's state isn't 'accepted'
def accepted?
state == 'accepted'
end
##
# Checks if the track is confirmed
# ====Returns
# * +true+ -> If the track's state is 'confirmed'
# * +false+ -> If the track's state isn't 'confirmed'
def confirmed?
state == 'confirmed'
end
##
# Checks if a self-organized track is accepted or confirmed
# ====Returns
# * +true+ -> If the track's state is 'accepted' or 'confirmed'
# * +false+ -> If the track's state is neither 'accepted' nor 'confirmed'
def self_organized_and_accepted_or_confirmed?
self_organized? && (accepted? || confirmed?)
end
def update_state(transition)
error = ''
begin
send(transition)
rescue Transitions::InvalidTransition => e
error += "State update failed. #{e.message} "
end
error += errors.full_messages.join(', ') unless save
error
end
private
def generate_guid
guid = SecureRandom.urlsafe_base64
# begin
# guid = SecureRandom.urlsafe_base64
# end while Person.where(:guid => guid).exists?
self.guid = guid
end
def capitalize_color
self.color = color.upcase if color.present?
end
def conference_id
program.conference_id
end
##
# Creates the role of the track organizer
def create_organizer_role
Role.where(name: 'track_organizer', resource: self).first_or_create(description: 'For the organizers of the Track')
end
def valid_dates
if start_date && program && program.conference && program.conference.start_date && (start_date < program.conference.start_date)
errors.add(:start_date, "can't be before the conference start date (#{program.conference.start_date})")
end
if end_date && program && program.conference && program.conference.start_date && (end_date < program.conference.start_date)
errors.add(:end_date, "can't be before the conference start date (#{program.conference.start_date})")
end
if start_date && program && program.conference && program.conference.end_date && (start_date > program.conference.end_date)
errors.add(:start_date, "can't be after the conference end date (#{program.conference.end_date})")
end
if end_date && program && program.conference && program.conference.end_date && (end_date > program.conference.end_date)
errors.add(:end_date, "can't be after the conference end date (#{program.conference.end_date})")
end
if start_date && end_date && (start_date > end_date)
errors.add(:start_date, 'can\'t be after the end date')
end
end
##
# Verify that the room is a room of the conference
def valid_room
if room && room.venue && room.venue.conference && program && program.conference && (program.conference != room.venue.conference)
errors.add(:room, "must be a room of #{program.conference.venue.name}")
end
end
end