mirror of
https://github.com/openSUSE/osem.git
synced 2026-08-13 19:54:02 +00:00
Registration for Events
This commit is contained in:
parent
f188fd5575
commit
01ec43e53a
35 changed files with 522 additions and 46 deletions
|
|
@ -581,6 +581,3 @@ DEPENDENCIES
|
|||
web-console (~> 2.0)
|
||||
webmock
|
||||
whenever
|
||||
|
||||
BUNDLED WITH
|
||||
1.11.2
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ module Admin
|
|||
load_and_authorize_resource :conference, find_by: :short_title
|
||||
load_and_authorize_resource :program, through: :conference, singleton: true
|
||||
load_and_authorize_resource :event, through: :program
|
||||
load_and_authorize_resource :events_registration, only: :toggle_attendance
|
||||
|
||||
before_action :get_event, except: [:index, :create]
|
||||
|
||||
|
|
@ -116,7 +117,7 @@ module Admin
|
|||
end
|
||||
else
|
||||
@url = admin_conference_program_event_path(@conference.short_title, @event)
|
||||
flash[:notice] = 'Update not successful. ' + @event.errors.full_messages.to_sentence
|
||||
flash[:error] = 'Update not successful. ' + @event.errors.full_messages.to_sentence
|
||||
render :edit
|
||||
end
|
||||
end
|
||||
|
|
@ -165,6 +166,20 @@ module Admin
|
|||
end
|
||||
end
|
||||
|
||||
def registrations
|
||||
@event_registrations = @event.events_registrations
|
||||
end
|
||||
|
||||
def toggle_attendance
|
||||
@events_registration.attended = !@events_registration.attended
|
||||
|
||||
if @events_registration.save
|
||||
head :ok
|
||||
else
|
||||
head :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def event_params
|
||||
|
|
@ -172,7 +187,7 @@ module Admin
|
|||
# Set also in proposals controller
|
||||
:title, :subtitle, :event_type_id, :abstract, :description, :require_registration, :difficulty_level_id,
|
||||
# Set only in admin/events controller
|
||||
:track_id, :state, :language, :start_time, :is_highlight,
|
||||
:track_id, :state, :language, :start_time, :is_highlight, :max_attendees,
|
||||
# Not used anymore?
|
||||
:proposal_additional_speakers, :user, :users_attributes)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ class ConferenceRegistrationsController < ApplicationController
|
|||
end
|
||||
|
||||
def show
|
||||
@workshops = @registration.workshops
|
||||
@total_price = Ticket.total_price(@conference, current_user)
|
||||
@tickets = current_user.ticket_purchases.where(conference_id: @conference.id)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -145,10 +145,14 @@ class ProposalController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def registrations; end
|
||||
|
||||
private
|
||||
|
||||
def event_params
|
||||
params.require(:event).permit(:title, :subtitle, :track_id, :event_type_id, :abstract, :description, :require_registration, :difficulty_level_id)
|
||||
params.require(:event).permit(:event_type_id, :track_id, :difficulty_level_id,
|
||||
:title, :subtitle, :abstract, :description,
|
||||
:require_registration, :max_attendees)
|
||||
end
|
||||
|
||||
def user_params
|
||||
|
|
|
|||
|
|
@ -1,4 +1,12 @@
|
|||
module ApplicationHelper
|
||||
##
|
||||
# ====Returns
|
||||
# * +String+ -> number of registrations / max allowed registrations
|
||||
def registered_text(event)
|
||||
return "Registered: #{event.registrations.count}/#{event.max_attendees}" if event.max_attendees
|
||||
"Registered: #{event.registrations.count}"
|
||||
end
|
||||
|
||||
# Set resource_name for devise so that we can call the devise help links (views/devise/shared/_links) from anywhere (eg sign_up form in proposal#new)
|
||||
def resource_name
|
||||
:user
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ class Event < ActiveRecord::Base
|
|||
has_many :commercials, as: :commercialable, dependent: :destroy
|
||||
belongs_to :event_type
|
||||
|
||||
has_and_belongs_to_many :registrations
|
||||
has_many :events_registrations
|
||||
has_many :registrations, through: :events_registrations
|
||||
|
||||
belongs_to :track
|
||||
belongs_to :room
|
||||
|
|
@ -32,6 +33,10 @@ class Event < ActiveRecord::Base
|
|||
validates :abstract, presence: true
|
||||
validates :event_type, presence: true
|
||||
validates :program, presence: true
|
||||
validates :max_attendees, numericality: { only_integer: true, greater_than_or_equal_to: 1, allow_nil: true }
|
||||
|
||||
validate :max_attendees_and_require_registration
|
||||
validate :max_attendees_no_more_than_room_size
|
||||
|
||||
scope :confirmed, -> { where(state: 'confirmed') }
|
||||
scope :highlighted, -> { where(is_highlight: true) }
|
||||
|
|
@ -64,6 +69,19 @@ class Event < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# 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?
|
||||
return false unless max_attendees
|
||||
registrations.count < max_attendees
|
||||
end
|
||||
|
||||
def voted?(event, user)
|
||||
event.votes.where('user_id = ?', user).first
|
||||
end
|
||||
|
|
@ -207,6 +225,21 @@ class Event < ActiveRecord::Base
|
|||
|
||||
private
|
||||
|
||||
##
|
||||
# If max_attendees variable is set (higher than 0)
|
||||
# variable require_registration must also be set
|
||||
def max_attendees_and_require_registration
|
||||
errors.add(:require_registration, 'must be enabled, when you set max_attendees') if max_attendees && !require_registration
|
||||
errors.add(:max_attendees, 'must be enabled, when you set require_registration') if require_registration && max_attendees.nil?
|
||||
end
|
||||
|
||||
##
|
||||
# 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
|
||||
|
||||
def abstract_limit
|
||||
# If we don't have an event type, there is no need to count anything
|
||||
return unless event_type && abstract
|
||||
|
|
|
|||
|
|
@ -1,4 +1,12 @@
|
|||
class EventsRegistration < ActiveRecord::Base
|
||||
belongs_to :registration
|
||||
belongs_to :event
|
||||
|
||||
has_one :user, through: :registration
|
||||
|
||||
delegate :name, to: :registration
|
||||
delegate :email, to: :registration
|
||||
|
||||
validates :event, :registration, presence: true
|
||||
validates :event, uniqueness: { scope: :registration }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,10 +8,21 @@ class Program < ActiveRecord::Base
|
|||
has_many :tracks, dependent: :destroy
|
||||
has_many :difficulty_levels, dependent: :destroy
|
||||
has_many :events, dependent: :destroy do
|
||||
def workshops
|
||||
def require_registration
|
||||
where(require_registration: true, state: :confirmed)
|
||||
end
|
||||
|
||||
def with_registration_open
|
||||
where(require_registration: true, state: :confirmed).
|
||||
map { |e| e if e.max_attendees > e.registrations.count }.compact
|
||||
end
|
||||
|
||||
# All confirmed events of the conference with attribute require_registration
|
||||
# excluding the events the user has already registered to
|
||||
def remaining_for_registration(registration)
|
||||
require_registration - registration.events
|
||||
end
|
||||
|
||||
def confirmed
|
||||
where(state: :confirmed)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class Registration < ActiveRecord::Base
|
|||
has_and_belongs_to_many :vchoices
|
||||
|
||||
has_many :events_registrations
|
||||
has_many :workshops, through: :events_registrations, source: :event
|
||||
has_many :events, through: :events_registrations
|
||||
|
||||
accepts_nested_attributes_for :user
|
||||
accepts_nested_attributes_for :qanswers
|
||||
|
|
@ -24,16 +24,40 @@ class Registration < ActiveRecord::Base
|
|||
|
||||
validates_uniqueness_of :user_id, scope: :conference_id, message: 'already Registered!'
|
||||
validate :registration_limit_not_exceed, on: :create
|
||||
validate :registration_to_events_only_if_present
|
||||
|
||||
after_create :set_week, :subscribe_to_conference, :send_registration_mail
|
||||
after_destroy :destroy_purchased_tickets
|
||||
|
||||
##
|
||||
# Makes a list of events that includes (in that order):
|
||||
# Events that require registration, and registration to them is still possible
|
||||
# Events to which the user is already registered to
|
||||
# ==== RETURNS
|
||||
# * +Array+ -> [event_to_register_to, event_already_registered_to]
|
||||
def events_ordered
|
||||
(conference.program.events.with_registration_open - events) + events
|
||||
end
|
||||
|
||||
def week
|
||||
created_at.strftime('%W').to_i
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
##
|
||||
# If the user registers to attend events that are already scheduled,
|
||||
# only allow registration to events if the user will be present
|
||||
# (based on arrival and departure attributes)
|
||||
# No validation if arrival/departure attributes are empty
|
||||
def registration_to_events_only_if_present
|
||||
if (arrival || departure) && events.pluck(:start_time).any?
|
||||
errors.add(:arrival, 'is too late! You cannot register for events that take place before your arrival') if events.pluck(:start_time).compact.map { |x| x < arrival }.any?
|
||||
|
||||
errors.add(:departure, 'is too early! You cannot register for events that take place after your departure') if events.pluck(:start_time).compact.map { |x| x > departure }.any?
|
||||
end
|
||||
end
|
||||
|
||||
def destroy_purchased_tickets
|
||||
ticket_purchased = TicketPurchase.where(conference_id: conference_id, user_id: user.id)
|
||||
ticket_purchased.destroy_all
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ class User < ActiveRecord::Base
|
|||
has_many :event_users, dependent: :destroy
|
||||
has_many :events, -> { uniq }, through: :event_users
|
||||
has_many :registrations, dependent: :destroy
|
||||
has_many :events_registrations, through: :registrations
|
||||
has_many :ticket_purchases, dependent: :destroy
|
||||
has_many :tickets, through: :ticket_purchases, source: :ticket
|
||||
has_many :votes, dependent: :destroy
|
||||
|
|
@ -53,10 +54,33 @@ class User < ActiveRecord::Base
|
|||
},
|
||||
presence: true
|
||||
|
||||
##
|
||||
# Checkes if the user attended the event
|
||||
# This is used for events that require registration
|
||||
# The user must have registered to attend the event
|
||||
# Gets an event
|
||||
# === Returns
|
||||
# * +true+ if the user attended the event
|
||||
# * +false+ if the user did not attend the event
|
||||
def attended_event? event
|
||||
event_registration = event.events_registrations.find_by(registration: self.registrations)
|
||||
|
||||
return false unless event_registration.present?
|
||||
event_registration.attended
|
||||
end
|
||||
|
||||
def name
|
||||
self[:name] || username
|
||||
end
|
||||
|
||||
##
|
||||
# Checks if a user has registered to an event
|
||||
# ====Returns
|
||||
# * +true+ or +false+
|
||||
def registered_to_event? event
|
||||
event.registrations.pluck(:id).include? self.registrations.find_by(conference_id: event.program.conference.id).id
|
||||
end
|
||||
|
||||
def subscribed? conference
|
||||
self.subscriptions.find_by(conference_id: conference.id).present?
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@
|
|||
%br
|
||||
%small
|
||||
= @event.subtitle
|
||||
= link_to 'Edit', edit_admin_conference_program_event_path(@conference.short_title, @event), class: 'btn btn-mini btn-primary pull-right'
|
||||
.btn-group.pull-right
|
||||
= link_to 'Registrations', registrations_admin_conference_program_event_path(@conference.short_title, @event), class: 'btn btn-success'
|
||||
= link_to 'Edit', edit_admin_conference_program_event_path(@conference.short_title, @event), class: 'btn btn-mini btn-primary'
|
||||
|
||||
.row
|
||||
.col-md-12
|
||||
|
|
@ -94,7 +96,8 @@
|
|||
off_color: 'warning',
|
||||
on_text: 'Yes',
|
||||
off_text: 'No' }
|
||||
|
||||
- if @event.require_registration
|
||||
= registered_text(@event)
|
||||
- if !@event.room.nil?
|
||||
%tr
|
||||
%td
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
%th
|
||||
%b Speaker
|
||||
%th
|
||||
%b Pre-registration
|
||||
%b Requires Registration
|
||||
%th
|
||||
%b Highlight
|
||||
%th
|
||||
|
|
@ -83,15 +83,18 @@
|
|||
- else
|
||||
Unknown speaker
|
||||
|
||||
%td{'data-order' => "#{event.require_registration}"}
|
||||
%td.text-center{'data-order' => "#{event.require_registration}"}
|
||||
= check_box_tag @conference.short_title, event.id, event.require_registration,
|
||||
method: :patch, url: "/admin/conference/#{@conference.short_title}/program/events/#{event.id}?event[require_registration]=",
|
||||
class: 'switch-checkbox', data: { size: 'small',
|
||||
off_color: 'warning',
|
||||
on_text: 'Yes',
|
||||
off_text: 'No' }
|
||||
- if event.require_registration
|
||||
%br
|
||||
= link_to registered_text(event), registrations_admin_conference_program_event_path(@conference.short_title, event), class: 'btn btn-xs btn-default'
|
||||
|
||||
%td{'data-order' => "#{event.is_highlight}"}
|
||||
%td.text-center{'data-order' => "#{event.is_highlight}"}
|
||||
= check_box_tag @conference.short_title, event.id, event.is_highlight,
|
||||
method: :patch, url: "/admin/conference/#{@conference.short_title}/program/events/#{event.id}?event[is_highlight]=",
|
||||
class: 'switch-checkbox', data: { size: 'small',
|
||||
|
|
|
|||
40
app/views/admin/events/registrations.html.haml
Normal file
40
app/views/admin/events/registrations.html.haml
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
.row
|
||||
.col-md-12
|
||||
.page-header
|
||||
%h1
|
||||
Registrations (#{@event_registrations.length}/#{@event.max_attendees})
|
||||
.text-muted
|
||||
for
|
||||
= @event.title
|
||||
|
||||
- if @event.room && (@event_registrations.length > @event.room.size)
|
||||
%b Attention:
|
||||
You have more registrations than the capacity of the room!
|
||||
|
||||
.well
|
||||
%table.table.table-hover.table-borderd.table-striped.datatable#registrations
|
||||
%thead
|
||||
%th
|
||||
%th Name
|
||||
%th Email
|
||||
%th Created At
|
||||
%th Attended
|
||||
%th Attended Conference
|
||||
%tbody
|
||||
- @event_registrations.each.with_index(1) do |event_registration, index|
|
||||
%tr
|
||||
%td= index
|
||||
%td= event_registration.name
|
||||
%td= event_registration.email
|
||||
%td= event_registration.created_at
|
||||
%td
|
||||
= check_box_tag @conference.short_title, @event.id, event_registration.attended, class: 'switch-checkbox', method: :patch, url: "/admin/conference/#{@conference.short_title}/program/events/#{@event.id}/toggle_attendance?events_registration_id=#{event_registration.id}&&event_registration[attended]=",
|
||||
data: { size: 'small',
|
||||
off_color: 'danger',
|
||||
on_text: 'Yes',
|
||||
off_text: 'No' }
|
||||
%td
|
||||
- if event_registration.registration.attended
|
||||
%i.fa.fa-check.text-success
|
||||
-else
|
||||
%i.fa.fa-close.text-danger
|
||||
25
app/views/admin/users/_event_registrations.html.haml
Normal file
25
app/views/admin/users/_event_registrations.html.haml
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
.row
|
||||
.col-md-12.page-header
|
||||
%h2
|
||||
Registrations to Events
|
||||
|
||||
.col-md-12
|
||||
.well
|
||||
%table.table.table-bordered.table-striped.table-hover.datatable#event_registrations
|
||||
%thead
|
||||
%th ID
|
||||
%th Conference
|
||||
%th Title
|
||||
%th Attended
|
||||
%tbody
|
||||
- @user.events_registrations.each do |event_registration|
|
||||
- event = event_registration.event
|
||||
%tr
|
||||
%td= event.id
|
||||
%td= link_to event.program.conference.short_title, admin_conference_path(event.program.conference.short_title)
|
||||
%td= link_to event.title, admin_conference_program_event_path(event.program.conference.short_title, event)
|
||||
%td
|
||||
- if @user.attended_event?(event)
|
||||
%i.fa.fa-check.text-success
|
||||
- else
|
||||
%i.fa.fa-times.text-danger
|
||||
|
|
@ -7,6 +7,8 @@
|
|||
- unless @user.events.blank?
|
||||
%li{class: "#{'active' if params[:tab] == 'submissions-content'}"}
|
||||
= link_to 'Submissions', '#submissions-content', 'data-toggle'=>'tab'
|
||||
%li{class: "#{'active' if params[:tab] == 'event_registrations-content'}"}
|
||||
= link_to 'Event Registrations', '#event_registrations', 'data-toggle'=>'tab'
|
||||
.tab-content
|
||||
#user-info-content.tab-pane{class: "#{'active' unless params[:tab] == 'submissions-content'}"}
|
||||
- if can? :edit, @user
|
||||
|
|
@ -31,3 +33,5 @@
|
|||
%td= @user.send(attr)
|
||||
#submissions-content.tab-pane{class: "#{'active' if params[:tab] == 'submissions-content'}"}
|
||||
= render 'submissions'
|
||||
#event_registrations.tab-pane{class: "#{'active' if params[:tab] == 'event_registrations'}"}
|
||||
= render 'event_registrations'
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
Registration for
|
||||
= @conference.title
|
||||
.row
|
||||
.col-md-6
|
||||
.col-md-8
|
||||
- if !current_user
|
||||
%legend
|
||||
%span
|
||||
|
|
|
|||
|
|
@ -1,8 +1,21 @@
|
|||
- if @conference.questions.any?
|
||||
= render partial: 'conference_registrations/questions', locals: { f: f }
|
||||
- if @conference.program.events.workshops.any?
|
||||
=f.inputs 'Pre-registration required for the following:' do
|
||||
= f.input :events, as: :check_boxes, label: false, collection: @conference.program.events.workshops
|
||||
- if @conference.program.events.with_registration_open.any? || @registration.events.any?
|
||||
= f.inputs 'Pre-registration required for the following:' do
|
||||
|
||||
- @registration.events_ordered.each do |event|
|
||||
%label
|
||||
= hidden_field_tag "registration[event_ids][]", nil
|
||||
= check_box_tag "registration[event_ids][]", event.id, event.registrations.include?(@registration)
|
||||
= event.title
|
||||
.text-muted
|
||||
= registered_text(event)
|
||||
- if event.scheduled?
|
||||
(Scheduled on: #{event.start_time.to_date})
|
||||
%br
|
||||
|
||||
|
||||
|
||||
= f.inputs 'Your Travel Info' do
|
||||
= f.input :arrival, as: :string, label: 'Your arrival time', input_html: { value: (f.object.arrival.to_formatted_s(:db_without_seconds) unless f.object.arrival.nil?), id: 'registration-arrival-datepicker',start_date: @conference.start_date,end_date: @conference.end_date,readonly: 'readonly' }
|
||||
= f.input :departure, as: :string, label: 'Your departure time', input_html: { value: (f.object.departure.to_formatted_s(:db_without_seconds) unless f.object.departure.nil?), id: 'registration-departure-datepicker', readonly: 'readonly' }
|
||||
|
|
|
|||
|
|
@ -54,18 +54,34 @@
|
|||
= qa.answer.title
|
||||
- else
|
||||
You haven't answered
|
||||
- if @workshops.any?
|
||||
- if @registration.events.any?
|
||||
.row
|
||||
.col-md-12
|
||||
%h4
|
||||
%span.fa-stack
|
||||
%i.fa.fa-square-o.fa-stack-2x
|
||||
%i.fa.fa-check.fa-stack-1x
|
||||
Event Registrations
|
||||
Registered to the following event(s)
|
||||
%ul
|
||||
- @workshops.each do |workshop|
|
||||
- @registration.events.each do |event|
|
||||
%li
|
||||
= link_to workshop.title, conference_program_proposal_path(@conference.short_title, workshop.id)
|
||||
= link_to event.title, conference_program_proposal_path(@conference.short_title, event.id)
|
||||
= '(' + registered_text(event) + ')'
|
||||
|
||||
- if @registration.conference.program.events.remaining_for_registration(@registration).any?
|
||||
.row
|
||||
.col-md-12
|
||||
%h4
|
||||
%span.fa-stack
|
||||
%i.fa.fa-square-o.fa-stack-2x
|
||||
%i.fa.fa-question.fa-stack-1x
|
||||
Events that require registration
|
||||
%ul
|
||||
- @registration.conference.program.events.remaining_for_registration(@registration).each do |event|
|
||||
%li
|
||||
= link_to event.title, conference_program_proposal_path(@conference.short_title, event.id)
|
||||
= '(' + registered_text(event) + ')'
|
||||
|
||||
- if @conference.tickets.any?
|
||||
.row
|
||||
.col-md-12
|
||||
|
|
|
|||
|
|
@ -42,7 +42,10 @@
|
|||
250
|
||||
words.
|
||||
|
||||
= f.input :require_registration, label: 'Require participants to register to your event'
|
||||
= f.inputs 'Enable pre-registration' do
|
||||
= f.input :require_registration, label: 'Require participants to register to your event'
|
||||
- message = @event.room ? "Value must be between 1 and #{@event.room.size}" : 'Check room capacity after scheduling.'
|
||||
= f.input :max_attendees, hint: 'The maximum number of participants. ' + message
|
||||
|
||||
- if current_user.has_any_role? :admin, { name: :organizer, resource: @conference }, { name: :cfp, resource: @conference }
|
||||
= f.input :is_highlight
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
.row
|
||||
.col-md-12.page-header
|
||||
%h1
|
||||
Proposals for
|
||||
Proposals for
|
||||
%span.notranslate
|
||||
= @conference.title
|
||||
|
||||
|
|
@ -68,9 +68,9 @@
|
|||
= event.event_type.title
|
||||
= "(#{event.event_type.length} min)"
|
||||
= "in #{event.track.name}" if event.track
|
||||
- if event.state == 'confirmed' && event.require_registration == true
|
||||
,
|
||||
Pre-registered: #{pre_registered(event).count}
|
||||
- if event.require_registration
|
||||
%br
|
||||
= link_to registered_text(event), registrations_conference_program_proposal_path(@conference.short_title, event), class: 'btn btn-xs btn-danger'
|
||||
|
||||
%td.col-md-2{style: "padding:20px 8px 20px 8px;"}
|
||||
= link_to 'Complete your proposal', 'javascript: void(0)', "type"=>"button", "data-trigger"=>"focus", "data-toggle"=>"popover", "title"=>"Your todo list", "data-content"=>"#{render partial: 'tooltip', locals: { event: event} }"
|
||||
|
|
|
|||
36
app/views/proposal/registrations.html.haml
Normal file
36
app/views/proposal/registrations.html.haml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
.container
|
||||
.row
|
||||
.col-md-10.col-md-offset-1
|
||||
.page-header
|
||||
%h1
|
||||
Registrations (#{@event.events_registrations.length}/#{@event.max_attendees})
|
||||
.text-muted
|
||||
for
|
||||
= @event.title
|
||||
|
||||
.well
|
||||
%table.table.table-hover.table-borderd.table-striped.datatable#registrations
|
||||
%thead
|
||||
%th
|
||||
%th Name
|
||||
%th Email
|
||||
%th Created AT
|
||||
%th Attended
|
||||
%th Attended Conference
|
||||
%tbody
|
||||
- @event.events_registrations.each.with_index(1) do |event_registration, index|
|
||||
%tr
|
||||
%td= index
|
||||
%td= event_registration.name
|
||||
%td= event_registration.email
|
||||
%td= event_registration.created_at
|
||||
%td.text-center
|
||||
- if event_registration.attended
|
||||
%i.fa.fa-check.text-success
|
||||
- else
|
||||
%i.fa.fa-times.text-danger
|
||||
%td
|
||||
- if event_registration.registration.attended
|
||||
%i.fa.fa-check.text-success
|
||||
-else
|
||||
%i.fa.fa-times.text-danger
|
||||
|
|
@ -7,10 +7,13 @@
|
|||
%br
|
||||
%small
|
||||
= @event.subtitle
|
||||
- if can? :schedule, @conference
|
||||
= link_to "Schedule", schedule_conference_path(@conference.short_title), :class =>"btn btn-success pull-right"
|
||||
- if can? :edit, @event
|
||||
= link_to "Edit", edit_conference_program_proposal_path(@conference.short_title, @event), :class => "btn btn-mini btn-primary pull-right"
|
||||
.btn-group.pull-right
|
||||
- if can? :update, @event
|
||||
= link_to 'Registrations', registrations_conference_program_proposal_path(@conference.short_title, @event), class: 'btn btn-mini btn-success'
|
||||
- if can? :edit, @event
|
||||
= link_to "Edit", edit_conference_program_proposal_path(@conference.short_title, @event), :class => "btn btn-mini btn-primary"
|
||||
- if can? :schedule, @conference
|
||||
= link_to "Schedule", schedule_conference_path(@conference.short_title), :class =>"btn btn-success"
|
||||
.row
|
||||
.col-md-3
|
||||
.speakerinfo
|
||||
|
|
@ -28,7 +31,6 @@
|
|||
= @speaker.affiliation
|
||||
-if @speaker.biography?
|
||||
= simple_format(@speaker.biography)
|
||||
|
||||
.col-md-9
|
||||
.row
|
||||
.col-md-12
|
||||
|
|
@ -76,5 +78,9 @@
|
|||
- if @event.difficulty_level_id
|
||||
%span.label{:style =>"background-color: #{@event.difficulty_level.color};"}
|
||||
= @event.difficulty_level.title
|
||||
- if @event.require_registration
|
||||
= link_to "Registration required!", new_conference_conference_registrations_path(@conference.short_title), :class => "btn btn-xs btn-warning"
|
||||
|
||||
- if @event.require_registration
|
||||
.col-md-12
|
||||
%dt Requires Registration:
|
||||
%dd
|
||||
= link_to "Yes (#{registered_text(@event)})", new_conference_conference_registrations_path(@conference.short_title), class: 'btn btn-xs btn-danger', disabled: !@event.registration_possible?
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ Osem::Application.routes.draw do
|
|||
resources :difficulty_levels
|
||||
resources :events do
|
||||
member do
|
||||
patch :toggle_attendance
|
||||
get :registrations
|
||||
post :comment
|
||||
patch :accept
|
||||
patch :confirm
|
||||
|
|
@ -99,7 +101,9 @@ Osem::Application.routes.draw do
|
|||
get 'commercials/render_commercial' => 'commercials#render_commercial'
|
||||
resources :commercials, only: [:create, :update, :destroy]
|
||||
member do
|
||||
get :registrations
|
||||
patch '/withdraw' => 'proposal#withdraw'
|
||||
get :registrations
|
||||
patch '/confirm' => 'proposal#confirm'
|
||||
patch '/restart' => 'proposal#restart'
|
||||
end
|
||||
|
|
|
|||
5
db/migrate/20160323154504_add_max_attendees_to_events.rb
Normal file
5
db/migrate/20160323154504_add_max_attendees_to_events.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
class AddMaxAttendeesToEvents < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :events, :max_attendees, :integer
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
class AddAttendedToEventsRegistrations < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :events_registrations, :attended, :boolean, default: false, null: false
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
class AddIdAndCreatedAtToEventsRegistrations < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :events_registrations, :id, :primary_key
|
||||
add_column :events_registrations, :created_at, :datetime
|
||||
end
|
||||
end
|
||||
11
db/schema.rb
11
db/schema.rb
|
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20160309183052) do
|
||||
ActiveRecord::Schema.define(version: 20160403214841) do
|
||||
|
||||
create_table "ahoy_events", force: :cascade do |t|
|
||||
t.uuid "visit_id", limit: 16
|
||||
|
|
@ -225,11 +225,14 @@ ActiveRecord::Schema.define(version: 20160309183052) do
|
|||
t.integer "week"
|
||||
t.boolean "is_highlight", default: false
|
||||
t.integer "program_id"
|
||||
t.integer "max_attendees"
|
||||
end
|
||||
|
||||
create_table "events_registrations", id: false, force: :cascade do |t|
|
||||
t.integer "registration_id"
|
||||
t.integer "event_id"
|
||||
create_table "events_registrations", force: :cascade do |t|
|
||||
t.integer "registration_id"
|
||||
t.integer "event_id"
|
||||
t.boolean "attended", default: false, null: false
|
||||
t.datetime "created_at"
|
||||
end
|
||||
|
||||
create_table "lodgings", force: :cascade do |t|
|
||||
|
|
|
|||
30
lib/tasks/events_registrations.rake
Normal file
30
lib/tasks/events_registrations.rake
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
namespace :events_registrations do
|
||||
desc "Deletes dupicate entries"
|
||||
task deduplicate: :environment do
|
||||
if ActiveRecord::Migrator.get_all_versions.include? 20160403214841
|
||||
duplicates = EventsRegistration.all.map { |er| er.id if er.valid? == false}.compact
|
||||
|
||||
puts "Duplicates found: #{duplicates.count}"
|
||||
if duplicates.count > 0
|
||||
puts "With IDs: #{duplicates}"
|
||||
end
|
||||
|
||||
EventsRegistration.all.each do |er|
|
||||
records = EventsRegistration.where(registration_id: er.registration_id, event_id: er.event_id)
|
||||
if records.count > 1
|
||||
# Iterate through duplicates (excluding 1st record)
|
||||
(1..(records.count - 1)).each do |i|
|
||||
puts "Deleting EventsRegistration record with ID #{records[i].id} ..."
|
||||
if records[i].destroy
|
||||
puts 'Succeeded!'
|
||||
else
|
||||
puts 'Faild!'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
puts 'Please migrate to run this task. Make sure your migration include 20160403214841'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -10,17 +10,20 @@ describe ConferenceRegistrationsController, type: :controller do
|
|||
describe 'GET #show' do
|
||||
before do
|
||||
@registration = create(:registration, conference: conference, user: user)
|
||||
@event_with_registration = create(:event, program: conference.program, require_registration: true, max_attendees: 5, state: 'confirmed')
|
||||
@event_without_registration = create(:event, program: conference.program, require_registration: true, max_attendees: 5, state: 'confirmed')
|
||||
@registration.events << @event_with_registration
|
||||
end
|
||||
|
||||
context 'successful request' do
|
||||
before do
|
||||
get :show, conference_id: conference.short_title
|
||||
|
||||
end
|
||||
|
||||
it 'assigns conference, registration and workshops variables' do
|
||||
it 'assigns variables' do
|
||||
expect(assigns(:conference)).to eq conference
|
||||
expect(assigns(:registration)).to eq @registration
|
||||
expect(assigns(:workshops)).to eq @registration.workshops
|
||||
end
|
||||
|
||||
it 'renders the show template' do
|
||||
|
|
|
|||
8
spec/factories/events_registrations.rb
Normal file
8
spec/factories/events_registrations.rb
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Read about factories at https://github.com/thoughtbot/factory_girl
|
||||
|
||||
FactoryGirl.define do
|
||||
factory :events_registration do
|
||||
event
|
||||
registration
|
||||
end
|
||||
end
|
||||
|
|
@ -1,10 +1,28 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe ApplicationHelper, type: :helper do
|
||||
let(:conference) { create(:conference) }
|
||||
let(:event) { create(:event, program: conference.program) }
|
||||
|
||||
describe 'show_roles' do
|
||||
it 'formats the hash passed' do
|
||||
roles = { 'organizer' => ['oSC16', 'oSC15'], 'cfp' => ['oSC16'] }
|
||||
expect(show_roles(roles)).to eq 'Organizer (oSC16, oSC15), Cfp (oSC16)'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#registered_text' do
|
||||
describe 'returns correct string' do
|
||||
it 'when there are no registrations' do
|
||||
expect(registered_text(event)).to eq 'Registered: 0'
|
||||
end
|
||||
|
||||
it 'when there is 1 registration' do
|
||||
event.require_registration = true
|
||||
event.max_attendees = 3
|
||||
event.registrations << create(:registration, user: event.submitter)
|
||||
expect(registered_text(event)).to eq 'Registered: 1/3'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ describe Event do
|
|||
describe 'association' do
|
||||
it { is_expected.to belong_to :program }
|
||||
it { is_expected.to belong_to :event_type }
|
||||
it { is_expected.to have_many :events_registrations }
|
||||
it { is_expected.to have_many :registrations }
|
||||
end
|
||||
|
||||
describe 'validation' do
|
||||
|
|
@ -22,6 +24,51 @@ describe Event do
|
|||
it { is_expected.to validate_presence_of(:program) }
|
||||
it { is_expected.to validate_presence_of(:event_type) }
|
||||
|
||||
describe '#max_attendees_and_require_registration' do
|
||||
it 'allows user to set max_attendees, only if require_registration is set' do
|
||||
event.require_registration = true
|
||||
event.max_attendees = 2
|
||||
|
||||
expect(event.valid?).to eq true
|
||||
end
|
||||
|
||||
it 'does not allow max_attendees to be set without require_registration' do
|
||||
event.max_attendees = 2
|
||||
|
||||
expect(event.valid?).to eq false
|
||||
expect(event.errors[:require_registration]).to eq ['must be enabled, when you set max_attendees']
|
||||
end
|
||||
|
||||
it 'does not allow require_registration to be set without max_attendees' do
|
||||
event.require_registration = true
|
||||
event.max_attendees = nil
|
||||
|
||||
expect(event.valid?).to eq false
|
||||
expect(event.errors[:max_attendees]).to eq ['must be enabled, when you set require_registration']
|
||||
end
|
||||
end
|
||||
|
||||
describe 'max_attendees_no_more_than_room_size' do
|
||||
before :each do
|
||||
event.room = create(:room, size: 3)
|
||||
event.require_registration = true
|
||||
end
|
||||
|
||||
it 'it is valid, if max_attendees is less than room size' do
|
||||
event.max_attendees = 2
|
||||
|
||||
expect(event.valid?).to eq true
|
||||
expect(event.errors.full_messages).to eq []
|
||||
end
|
||||
|
||||
it 'it is not valid, if max_attendees attribute is bigger than size of room' do
|
||||
event.max_attendees = 4
|
||||
|
||||
expect(event.valid?).to eq false
|
||||
expect(event.errors[:max_attendees]).to eq ['cannot be more than the room\'s capacity (3)']
|
||||
end
|
||||
end
|
||||
|
||||
describe '#abstract_limit' do
|
||||
before :each do
|
||||
event.event_type.maximum_abstract_length = 2
|
||||
|
|
@ -89,6 +136,41 @@ describe Event do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#scheduled?' do
|
||||
it { expect(event.scheduled?).to eq false }
|
||||
it 'returns true if the event is scheduled' do
|
||||
event.room = create(:room)
|
||||
event.start_time = conference.start_date.to_time
|
||||
expect(event.scheduled?).to eq true
|
||||
end
|
||||
end
|
||||
|
||||
describe '#registration_possible?' do
|
||||
describe 'when the event requires registration' do
|
||||
before :each do
|
||||
event.require_registration = true
|
||||
event.max_attendees = 3
|
||||
event.registrations << create(:registration)
|
||||
end
|
||||
|
||||
it 'returns true, if the limit has not been reached' do
|
||||
expect(event.registration_possible?).to eq true
|
||||
end
|
||||
|
||||
it 'returns false, if the limit has been reached' do
|
||||
event.registrations << create(:registration)
|
||||
event.registrations << create(:registration)
|
||||
expect(event.registration_possible?).to eq false
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when the event does not require registration' do
|
||||
it 'returns false' do
|
||||
expect(event.registration_possible?).to eq false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#voted?' do
|
||||
it 'returns nil if the event has no votes' do
|
||||
expect(event.voted?(event, user)).to eq nil
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ describe 'Registration' do
|
|||
subject { create(:registration) }
|
||||
let!(:user) { create(:user) }
|
||||
let!(:conference) { create(:conference) }
|
||||
let!(:registration1) { create(:registration, conference: conference, user: user) }
|
||||
let!(:registration) { create(:registration, conference: conference, user: user) }
|
||||
|
||||
describe 'validation' do
|
||||
it 'has a valid factory' do
|
||||
|
|
@ -33,7 +33,7 @@ describe 'Registration' do
|
|||
it { is_expected.to have_and_belong_to_many(:qanswers) }
|
||||
it { is_expected.to have_and_belong_to_many(:vchoices) }
|
||||
it { is_expected.to have_many(:events_registrations) }
|
||||
it { is_expected.to have_many(:workshops) }
|
||||
it { is_expected.to have_many(:events) }
|
||||
end
|
||||
|
||||
describe 'after create' do
|
||||
|
|
@ -69,12 +69,34 @@ describe 'Registration' do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'registration_to_events_only_if_present' do
|
||||
context 'valid' do
|
||||
it 'when user registers for events happening while user is at the conference' do
|
||||
registration.arrival = conference.start_date
|
||||
registration.departure = conference.end_date
|
||||
registration.events << create(:event, program: conference.program, start_time: conference.end_date)
|
||||
|
||||
expect(registration.valid?).to eq true
|
||||
end
|
||||
end
|
||||
|
||||
context 'invalid' do
|
||||
it 'when user registers for events happening while user is not at the conference' do
|
||||
registration.arrival = conference.start_date
|
||||
registration.departure = conference.start_date
|
||||
registration.events << create(:event, program: conference.program, start_time: conference.end_date)
|
||||
|
||||
expect(registration.valid?).to eq false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#destroy_purchased_tickets' do
|
||||
it 'destroys purchased tickets if tickets are purchased' do
|
||||
create(:ticket_purchase, conference: conference, user: user)
|
||||
expect(user.registrations.size).to be 1
|
||||
expect(user.ticket_purchases.size).to be 1
|
||||
registration1.destroy
|
||||
registration.destroy
|
||||
expect(user.registrations.size).to be 0
|
||||
expect(user.ticket_purchases.size).to be 0
|
||||
end
|
||||
|
|
@ -82,7 +104,7 @@ describe 'Registration' do
|
|||
it 'destroys no tickets if no tickets are purchased' do
|
||||
expect(user.registrations.size).to be 1
|
||||
expect(user.ticket_purchases.size).to be 0
|
||||
registration1.destroy
|
||||
registration.destroy
|
||||
expect(user.registrations.size).to be 0
|
||||
expect(user.ticket_purchases.size).to be 0
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ describe User do
|
|||
let(:organizer) { create(:user, role_ids: [organizer_role.id]) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
let(:event1) { create(:event, program: conference.program) }
|
||||
let(:another_conference) { create(:conference) }
|
||||
let(:event2) { create(:event, program: another_conference.program) }
|
||||
|
||||
describe 'validation' do
|
||||
it 'has a valid factory' do
|
||||
expect(build(:user)).to be_valid
|
||||
|
|
@ -26,6 +30,7 @@ describe User do
|
|||
it { is_expected.to have_many(:event_users).dependent(:destroy) }
|
||||
it { is_expected.to have_many(:events).through(:event_users) }
|
||||
it { is_expected.to have_many(:registrations).dependent(:destroy) }
|
||||
it { is_expected.to have_many(:events_registrations).through(:registrations) }
|
||||
it { is_expected.to have_many(:ticket_purchases).dependent(:destroy) }
|
||||
it { is_expected.to have_many(:tickets).through(:ticket_purchases) }
|
||||
it { is_expected.to have_many(:votes).dependent(:destroy) }
|
||||
|
|
@ -341,4 +346,17 @@ describe User do
|
|||
expect(second_user.is_admin).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe 'has_many events_registrations' do
|
||||
before :each do
|
||||
registration1 = create(:registration, user: user, conference: conference)
|
||||
registration2 = create(:registration, user: user, conference: another_conference)
|
||||
@events_registration1 = create(:events_registration, registration: registration1, event: event1)
|
||||
@events_registration2 = create(:events_registration, registration: registration2, event: event2)
|
||||
end
|
||||
|
||||
it 'returns all the events the user registered to' do
|
||||
expect(user.events_registrations).to eq [@events_registration1, @events_registration2]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ describe 'admin/events/index' do
|
|||
expect(rendered).to have_selector('table thead th:nth-of-type(2)', text: 'Title')
|
||||
expect(rendered).to have_selector('table thead th:nth-of-type(3)', text: 'Submitter')
|
||||
expect(rendered).to have_selector('table thead th:nth-of-type(4)', text: 'Speaker')
|
||||
expect(rendered).to have_selector('table thead th:nth-of-type(5)', text: 'Pre-registration')
|
||||
expect(rendered).to have_selector('table thead th:nth-of-type(5)', text: 'Requires Registration')
|
||||
expect(rendered).to have_selector('table thead th:nth-of-type(6)', text: 'Highlight')
|
||||
expect(rendered).to have_selector('table thead th:nth-of-type(7)', text: 'Type')
|
||||
expect(rendered).to have_selector('table thead th:nth-of-type(8)', text: 'Track')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue