effective_events 0.19.2 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/javascripts/effective_events/base.js +32 -0
- data/app/controllers/effective/event_registrants_select2_ajax_controller.rb +61 -0
- data/app/controllers/effective/event_registrations_controller.rb +17 -1
- data/app/datatables/effective_event_registrants_datatable.rb +11 -11
- data/app/datatables/effective_event_registrations_datatable.rb +2 -1
- data/app/helpers/effective_events_helper.rb +2 -19
- data/app/mailers/effective/events_mailer.rb +1 -1
- data/app/models/concerns/effective_events_event_registration.rb +141 -51
- data/app/models/effective/event.rb +32 -12
- data/app/models/effective/event_notification.rb +1 -1
- data/app/models/effective/event_registrant.rb +171 -45
- data/app/models/effective/event_ticket.rb +20 -17
- data/app/models/effective/event_ticket_selection.rb +28 -0
- data/app/views/admin/event_registrants/_form.html.haml +16 -3
- data/app/views/admin/event_tickets/_form.html.haml +1 -1
- data/app/views/effective/event_registrants/_fields.html.haml +47 -28
- data/app/views/effective/event_registrations/_details.html.haml +1 -0
- data/app/views/effective/event_registrations/_fields_event_registrants.html.haml +26 -0
- data/app/views/effective/event_registrations/_fields_event_ticket_selections.html.haml +85 -0
- data/app/views/effective/event_registrations/_form_blank_registrants.html.haml +12 -14
- data/app/views/effective/event_registrations/_layout.html.haml +9 -1
- data/app/views/effective/event_registrations/billing.html.haml +1 -1
- data/app/views/effective/event_registrations/details.html.haml +10 -0
- data/app/views/effective/event_registrations/summary.html.haml +2 -2
- data/app/views/effective/event_registrations/tickets.html.haml +3 -13
- data/app/views/effective/events/show.html.haml +34 -34
- data/config/effective_events.rb +11 -4
- data/config/routes.rb +5 -0
- data/db/migrate/101_create_effective_events.rb +16 -1
- data/lib/effective_events/version.rb +1 -1
- data/lib/effective_events.rb +6 -4
- metadata +8 -7
- data/app/views/effective/event_registrants/_fields_member_only.html.haml +0 -10
- data/app/views/effective/event_registrants/_fields_member_or_non_member.html.haml +0 -34
- data/app/views/effective/event_registrants/_fields_questions.html.haml +0 -8
- data/app/views/effective/event_registrants/_fields_regular.html.haml +0 -8
- data/app/views/effective/event_registrations/_event_tickets.html.haml +0 -68
@@ -2,10 +2,13 @@
|
|
2
2
|
|
3
3
|
module Effective
|
4
4
|
class EventRegistrant < ActiveRecord::Base
|
5
|
+
include ActionView::Helpers::TagHelper
|
6
|
+
|
5
7
|
self.table_name = (EffectiveEvents.event_registrants_table_name || :event_registrants).to_s
|
6
8
|
|
7
|
-
PERMITTED_BLANK_REGISTRANT_CHANGES = ["first_name", "last_name", "email", "company", "user_id", "user_type", "
|
8
|
-
|
9
|
+
PERMITTED_BLANK_REGISTRANT_CHANGES = ["first_name", "last_name", "email", "company", "user_id", "user_type", "organization_id", "organization_type", "blank_registrant", "response1", "response2", "response3"]
|
10
|
+
|
11
|
+
attr_accessor :building_user_and_organization
|
9
12
|
|
10
13
|
acts_as_purchasable
|
11
14
|
acts_as_archived
|
@@ -14,7 +17,7 @@ module Effective
|
|
14
17
|
|
15
18
|
belongs_to :event, counter_cache: true
|
16
19
|
|
17
|
-
# Basically a category containing all the pricing and unique info about
|
20
|
+
# Basically a category containing all the pricing and unique info about this registrant
|
18
21
|
belongs_to :event_ticket
|
19
22
|
|
20
23
|
# Every event registrant is charged to a owner
|
@@ -23,20 +26,26 @@ module Effective
|
|
23
26
|
# This fee when checked out through the event registration
|
24
27
|
belongs_to :event_registration, polymorphic: true, optional: true
|
25
28
|
|
26
|
-
#
|
29
|
+
# The user for this registrant
|
27
30
|
belongs_to :user, polymorphic: true, optional: true
|
31
|
+
accepts_nested_attributes_for :user
|
32
|
+
|
33
|
+
# The organization for this registrant
|
34
|
+
belongs_to :organization, polymorphic: true, optional: true
|
35
|
+
accepts_nested_attributes_for :organization
|
28
36
|
|
29
37
|
effective_resource do
|
30
38
|
first_name :string
|
31
39
|
last_name :string
|
32
40
|
email :string
|
33
|
-
company :string
|
41
|
+
company :string # Organization name
|
34
42
|
|
35
|
-
blank_registrant
|
36
|
-
member_or_non_member_choice :string # Used by Member or Non-Member tickets to indicate a member or non-member
|
43
|
+
blank_registrant :boolean # Leave details and come back later
|
37
44
|
|
38
45
|
waitlisted :boolean
|
39
46
|
promoted :boolean # An admin marked this registrant as promoted from the waitlist
|
47
|
+
|
48
|
+
selected_at :datetime # When the event registration was selected by a user on the tickets! step
|
40
49
|
registered_at :datetime # When the order is deferred or purchased
|
41
50
|
|
42
51
|
# Question Responses
|
@@ -58,7 +67,7 @@ module Effective
|
|
58
67
|
timestamps
|
59
68
|
end
|
60
69
|
|
61
|
-
scope :sorted, -> { order(:
|
70
|
+
scope :sorted, -> { order(:event_ticket_id, :id) }
|
62
71
|
scope :deep, -> { includes(:event, :event_ticket, :owner) }
|
63
72
|
scope :registered, -> { where.not(registered_at: nil) }
|
64
73
|
|
@@ -67,12 +76,31 @@ module Effective
|
|
67
76
|
self.owner ||= event_registration.owner
|
68
77
|
end
|
69
78
|
|
70
|
-
|
71
|
-
|
72
|
-
|
79
|
+
with_options(unless: -> { purchased? && !blank_registrant_was }) do
|
80
|
+
before_validation(if: -> { blank_registrant? }) do
|
81
|
+
assign_attributes(user: nil, organization: nil, first_name: nil, last_name: nil, email: nil, company: nil)
|
82
|
+
end
|
83
|
+
|
84
|
+
before_validation(if: -> { user.blank? }) do
|
85
|
+
assign_attributes(building_user_and_organization: true) # For member-only ticket validations
|
86
|
+
end
|
73
87
|
|
74
|
-
|
75
|
-
|
88
|
+
before_validation(if: -> { user.blank? && first_name.present? && last_name.present? && email.present? }) do
|
89
|
+
build_user() if EffectiveEvents.create_users
|
90
|
+
build_organization_and_representative() if EffectiveEvents.organization_enabled?
|
91
|
+
end
|
92
|
+
|
93
|
+
before_validation(if: -> { user.present? }) do
|
94
|
+
assign_attributes(first_name: user.first_name, last_name: user.last_name, email: (user.try(:public_email).presence || user.email))
|
95
|
+
end
|
96
|
+
|
97
|
+
before_validation(if: -> { organization.blank? && user.present? && user.class.try(:effective_memberships_organization_user?) }) do
|
98
|
+
assign_attributes(company: user.organizations.first.to_s.presence) if company.blank?
|
99
|
+
end
|
100
|
+
|
101
|
+
before_validation(if: -> { organization.present? }) do
|
102
|
+
assign_attributes(company: organization.to_s)
|
103
|
+
end
|
76
104
|
end
|
77
105
|
|
78
106
|
before_validation(if: -> { event_ticket.present? }, unless: -> { purchased? }) do
|
@@ -83,35 +111,44 @@ module Effective
|
|
83
111
|
errors.add(:waitlisted, 'is not permitted for a non-waitlist event ticket') if waitlisted? && !event_ticket.waitlist?
|
84
112
|
end
|
85
113
|
|
86
|
-
validates :user_id, uniqueness: { scope: [:event_id], allow_blank: true, message: 'is already registered for this event' }
|
87
114
|
validates :price, presence: true, numericality: { greater_than_or_equal_to: 0 }
|
88
115
|
validates :email, email: true
|
89
116
|
|
90
|
-
#
|
91
|
-
|
92
|
-
|
93
|
-
|
117
|
+
# This works for persisted and adding a new one. But not adding two at same time in a registration
|
118
|
+
validates :user_id, uniqueness: { scope: [:event_id], allow_blank: true, message: 'is already registered for this event' }
|
119
|
+
|
120
|
+
# First name, last name and email are always required fields on details
|
121
|
+
validates :first_name, presence: true, if: -> { registrant_validations_enabled? }
|
122
|
+
validates :last_name, presence: true, if: -> { registrant_validations_enabled? }
|
123
|
+
validates :email, presence: true, if: -> { registrant_validations_enabled? }
|
124
|
+
|
125
|
+
# User, company and organization conditionall required
|
126
|
+
validates :user, presence: true, if: -> { registrant_validations_enabled? && EffectiveEvents.create_users }
|
127
|
+
validates :company, presence: true, if: -> { registrant_validations_enabled? && EffectiveEvents.company_or_organization_required }
|
128
|
+
validates :organization, presence: true, if: -> { registrant_validations_enabled? && EffectiveEvents.company_or_organization_required && EffectiveEvents.organization_enabled? }
|
94
129
|
|
95
|
-
#
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
130
|
+
# Member ticket: company name is locked in. you can only add to your own company
|
131
|
+
validate(if: -> { registrant_validations_enabled? && event_ticket&.member_only? }) do
|
132
|
+
if building_user_and_organization && owner.present? && Array(owner.try(:organizations)).exclude?(organization)
|
133
|
+
errors.add(:organization_id, "must be your own for member-only tickets")
|
134
|
+
end
|
135
|
+
|
136
|
+
errors.add(:user_id, 'must be a member to register for member-only tickets') unless member_present?
|
101
137
|
end
|
102
138
|
|
103
|
-
#
|
104
|
-
|
139
|
+
# Copy any user errors from build_user_and_organization() into the registrant
|
140
|
+
after_validation(if: -> { user && user.new_record? && user.errors.present? }) do
|
141
|
+
errors.add(:first_name, user.errors[:first_name].join(', ')) if user.errors[:first_name].present?
|
142
|
+
errors.add(:last_name, user.errors[:last_name].join(', ')) if user.errors[:last_name].present?
|
143
|
+
errors.add(:email, user.errors[:email].join(', ')) if user.errors[:email].present?
|
105
144
|
|
106
|
-
|
107
|
-
|
108
|
-
validates :last_name, presence: true, unless: -> { EffectiveEvents.event_registrant_required_fields.exclude?(:last_name) }
|
109
|
-
validates :email, presence: true, unless: -> { EffectiveEvents.event_registrant_required_fields.exclude?(:email) }
|
110
|
-
validates :company, presence: true, unless: -> { EffectiveEvents.event_registrant_required_fields.exclude?(:company) }
|
145
|
+
others = user.errors.reject { |error| [:first_name, :last_name, :email].include?(error.attribute) }
|
146
|
+
errors.add(:base, others.map(&:full_message).join(', ')) if others.present?
|
111
147
|
end
|
112
148
|
|
113
|
-
|
114
|
-
|
149
|
+
# Copy any organization errors from build_user_and_organization() into the registrant
|
150
|
+
after_validation(if: -> { organization && organization.new_record? && organization.errors.present? }) do
|
151
|
+
errors.add(:company, organization.errors.full_messages.join(', '))
|
115
152
|
end
|
116
153
|
|
117
154
|
after_defer do
|
@@ -127,7 +164,7 @@ module Effective
|
|
127
164
|
end
|
128
165
|
|
129
166
|
def title
|
130
|
-
[event_ticket
|
167
|
+
["#{event_ticket} - #{name}", details.presence].compact.join(' ').html_safe
|
131
168
|
end
|
132
169
|
|
133
170
|
def name
|
@@ -140,20 +177,42 @@ module Effective
|
|
140
177
|
end
|
141
178
|
end
|
142
179
|
|
180
|
+
def details
|
181
|
+
[
|
182
|
+
(content_tag(:span, 'Member', class: 'badge badge-warning') if member_ticket?),
|
183
|
+
(content_tag(:span, 'Waitlist', class: 'badge badge-warning') if waitlisted_not_promoted?),
|
184
|
+
(content_tag(:span, 'Archived', class: 'badge badge-warning') if event_ticket&.archived?)
|
185
|
+
].compact.join(' ').html_safe
|
186
|
+
end
|
187
|
+
|
188
|
+
def purchasable_name
|
189
|
+
["#{event_ticket} - #{name}", details.presence].compact.join('<br>').html_safe
|
190
|
+
end
|
191
|
+
|
143
192
|
def last_first_name
|
144
|
-
first_name.present? ? "#{last_name}, #{first_name}" : "GUEST"
|
193
|
+
(first_name.present? && last_name.present?) ? "#{last_name}, #{first_name}" : "GUEST"
|
145
194
|
end
|
146
195
|
|
147
|
-
|
148
|
-
|
196
|
+
# We create registrants on the tickets step. But don't enforce validations until the details step.
|
197
|
+
def registrant_validations_enabled?
|
198
|
+
return false if blank_registrant? # They want to come back later
|
199
|
+
|
200
|
+
return true if event_registration.blank? # If we're creating in an Admin area
|
201
|
+
return false if event_ticket.blank? # Invalid anyway
|
202
|
+
|
203
|
+
event_registration.current_step == :details
|
149
204
|
end
|
150
205
|
|
151
|
-
def
|
152
|
-
|
206
|
+
def member_present?
|
207
|
+
user.try(:is?, :member) || organization.try(:is?, :member)
|
153
208
|
end
|
154
209
|
|
155
|
-
def
|
156
|
-
|
210
|
+
def member_ticket?
|
211
|
+
return false if event_ticket.blank?
|
212
|
+
return true if event_ticket.member_only?
|
213
|
+
return true if event_ticket.member_or_non_member? && member_present?
|
214
|
+
|
215
|
+
false
|
157
216
|
end
|
158
217
|
|
159
218
|
def present_registrant?
|
@@ -168,10 +227,19 @@ module Effective
|
|
168
227
|
event_ticket&.qb_item_name
|
169
228
|
end
|
170
229
|
|
230
|
+
def selected?
|
231
|
+
selected_at.present?
|
232
|
+
end
|
233
|
+
|
171
234
|
def registered?
|
172
235
|
registered_at.present?
|
173
236
|
end
|
174
237
|
|
238
|
+
def selected_not_expired?
|
239
|
+
return false unless EffectiveEvents.EventRegistration.selection_window.present?
|
240
|
+
selected_at.present? && (selected_at + EffectiveEvents.EventRegistration.selection_window > Time.zone.now)
|
241
|
+
end
|
242
|
+
|
175
243
|
# Called by an event_registration after_defer and after_purchase
|
176
244
|
def registered!
|
177
245
|
self.registered_at ||= Time.zone.now
|
@@ -219,10 +287,6 @@ module Effective
|
|
219
287
|
true
|
220
288
|
end
|
221
289
|
|
222
|
-
def registered?
|
223
|
-
registered_at.present?
|
224
|
-
end
|
225
|
-
|
226
290
|
def event_ticket_price
|
227
291
|
raise('expected an event') if event.blank?
|
228
292
|
raise('expected an event ticket') if event_ticket.blank?
|
@@ -246,6 +310,68 @@ module Effective
|
|
246
310
|
|
247
311
|
private
|
248
312
|
|
313
|
+
def build_user
|
314
|
+
raise('is already purchased') if purchased?
|
315
|
+
raise('expected no user') unless user.blank?
|
316
|
+
raise('expected a first_name') unless first_name.present?
|
317
|
+
raise('expected a last_name') unless last_name.present?
|
318
|
+
raise('expected a email') unless email.present?
|
319
|
+
|
320
|
+
return if user_type.blank?
|
321
|
+
|
322
|
+
# Add User
|
323
|
+
user_klass = user_type.constantize
|
324
|
+
|
325
|
+
# First we lookup the user by email. If they actually exist we ignore all other fields
|
326
|
+
existing_user = user_klass.find_by_any_email(email.strip.downcase)
|
327
|
+
|
328
|
+
if existing_user.present?
|
329
|
+
assign_attributes(user: existing_user)
|
330
|
+
|
331
|
+
if EffectiveEvents.organization_enabled? && user_klass.try(:effective_memberships_organization_user?)
|
332
|
+
assign_attributes(organization: existing_user.organizations.first) if existing_user.organizations.present?
|
333
|
+
end
|
334
|
+
else
|
335
|
+
# Otherwise create a new user
|
336
|
+
new_user = user_klass.create(
|
337
|
+
first_name: first_name.strip,
|
338
|
+
last_name: last_name.strip,
|
339
|
+
email: email.strip.downcase,
|
340
|
+
password: SecureRandom.base64(12) + '!@#123abcABC-'
|
341
|
+
)
|
342
|
+
|
343
|
+
assign_attributes(user: new_user)
|
344
|
+
end
|
345
|
+
|
346
|
+
user.valid?
|
347
|
+
end
|
348
|
+
|
349
|
+
# The organization might already be set here
|
350
|
+
def build_organization_and_representative
|
351
|
+
raise('is already purchased') if purchased?
|
352
|
+
|
353
|
+
return if organization_type.blank?
|
354
|
+
|
355
|
+
# We previously created an invalid user
|
356
|
+
return if user.present? && user.errors.present?
|
357
|
+
|
358
|
+
# Add Organization and representative
|
359
|
+
organization_klass = organization_type.constantize
|
360
|
+
|
361
|
+
# Find or create the organization
|
362
|
+
if organization.present?
|
363
|
+
user.build_representative(organization: organization) if user.present?
|
364
|
+
elsif company.present?
|
365
|
+
new_organization = organization_klass.where(title: company.strip).first
|
366
|
+
new_organization ||= organization_klass.create(title: company.strip, email: email.strip.downcase)
|
367
|
+
assign_attributes(organization: new_organization)
|
368
|
+
|
369
|
+
user.build_representative(organization: new_organization) if user.present?
|
370
|
+
end
|
371
|
+
|
372
|
+
true
|
373
|
+
end
|
374
|
+
|
249
375
|
def assign_price
|
250
376
|
raise('is already purchased') if purchased?
|
251
377
|
|
@@ -69,35 +69,38 @@ module Effective
|
|
69
69
|
validates :early_bird_price, numericality: { greater_than_or_equal_to: 0, allow_blank: true }
|
70
70
|
|
71
71
|
validates :capacity, numericality: { greater_than_or_equal_to: 0, allow_blank: true }
|
72
|
+
validates :capacity, presence: { message: 'must be present when using the waitlist'}, if: -> { waitlist? }
|
72
73
|
|
73
74
|
def to_s
|
74
75
|
title.presence || 'New Event Ticket'
|
75
76
|
end
|
76
77
|
|
77
|
-
|
78
|
-
|
79
|
-
return
|
78
|
+
def capacity_selectable(except: nil)
|
79
|
+
return nil if capacity.blank?
|
80
|
+
return nil if waitlist?
|
80
81
|
|
81
|
-
|
82
|
-
|
82
|
+
capacity_available(except: except)
|
83
|
+
end
|
83
84
|
|
84
|
-
|
85
|
-
|
86
|
-
|
85
|
+
def capacity_available(except: nil)
|
86
|
+
return nil if capacity.blank?
|
87
|
+
[(capacity - capacity_taken(except: except)), 0].max
|
88
|
+
end
|
87
89
|
|
88
|
-
|
89
|
-
|
90
|
-
|
90
|
+
def capacity_taken(except: nil)
|
91
|
+
registered_or_selected_event_registrants(except: except).reject(&:waitlisted?).length
|
92
|
+
end
|
91
93
|
|
92
|
-
|
93
|
-
|
94
|
+
def registered_or_selected_event_registrants(except: nil)
|
95
|
+
raise('expected except to be an EventRegistration') if except && !except.class.try(:effective_events_event_registration?)
|
94
96
|
|
95
|
-
|
97
|
+
event_registrants.select do |er|
|
98
|
+
(er.registered? || er.selected_not_expired?) && (except.blank? || er.event_registration_id != except.id)
|
99
|
+
end
|
96
100
|
end
|
97
101
|
|
98
|
-
def
|
99
|
-
|
100
|
-
[(capacity - registered_event_registrants_count), 0].max
|
102
|
+
def registered_or_selected_event_registrants_count
|
103
|
+
registered_or_selected_event_registrants.count
|
101
104
|
end
|
102
105
|
|
103
106
|
def registered_event_registrants_count
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Form object to select a # of tickets on the EventRegistration form
|
4
|
+
|
5
|
+
module Effective
|
6
|
+
class EventTicketSelection < ActiveRecord::Base
|
7
|
+
self.table_name = (EffectiveEvents.event_ticket_selections_table_name || :event_ticket_selections).to_s
|
8
|
+
|
9
|
+
belongs_to :event_registration, polymorphic: true
|
10
|
+
belongs_to :event_ticket
|
11
|
+
|
12
|
+
effective_resource do
|
13
|
+
quantity :integer
|
14
|
+
|
15
|
+
timestamps
|
16
|
+
end
|
17
|
+
|
18
|
+
scope :sorted, -> { order(:id) }
|
19
|
+
scope :deep, -> { includes(:event_registration, :event_ticket) }
|
20
|
+
|
21
|
+
validates :quantity, numericality: { greater_than_or_equal_to: 0 }
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
persisted? ? "#{quantity}x #{event_ticket}": model_name.human
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -9,10 +9,10 @@
|
|
9
9
|
- if f.object.new_record?
|
10
10
|
-# User
|
11
11
|
- klass = (f.object.owner || current_user).class
|
12
|
-
- ajax_url = (
|
12
|
+
- ajax_url = (effective_resources.users_admin_select2_ajax_index_path unless Rails.env.test?)
|
13
13
|
|
14
14
|
= f.hidden_field :owner_type, value: klass.name
|
15
|
-
= f.select :owner_id, klass.all, ajax_url: ajax_url, label: 'User'
|
15
|
+
= f.select :owner_id, klass.all, ajax_url: ajax_url, label: 'Registration User'
|
16
16
|
- else
|
17
17
|
= f.static_field :owner
|
18
18
|
|
@@ -20,7 +20,20 @@
|
|
20
20
|
|
21
21
|
#effective-events-event-registrant-ajax
|
22
22
|
- if f.object.event.present?
|
23
|
-
|
23
|
+
.card
|
24
|
+
.card-body
|
25
|
+
- if f.object.purchased?
|
26
|
+
= f.static_field :event_ticket, label: 'Purchased ticket'
|
27
|
+
|
28
|
+
= f.select :event_ticket_id, effective_events_event_tickets_collection(f.object.event, namespace), required: true
|
29
|
+
|
30
|
+
- if f.object.event.allow_blank_registrants? && (f.object.new_record? || f.object.blank_registrant?)
|
31
|
+
= f.check_box :blank_registrant, label: "I will return and add this ticket's information later"
|
32
|
+
- else
|
33
|
+
= f.hidden_field :blank_registrant, value: false
|
34
|
+
|
35
|
+
= f.show_if(:blank_registrant, false) do
|
36
|
+
= render('effective/event_registrants/fields', f: f)
|
24
37
|
|
25
38
|
= f.check_box :archived, label: "Archive this registrant. It will be displayed as archived on the owner's event registration"
|
26
39
|
|
@@ -11,7 +11,7 @@
|
|
11
11
|
= f.show_if(:category, 'Regular') do
|
12
12
|
.alert.alert-info.mb-4
|
13
13
|
%strong Regular Ticket:
|
14
|
-
Anyone will be able to purchase this ticket.
|
14
|
+
Anyone will be able to purchase this ticket. Only the regular price applies.
|
15
15
|
|
16
16
|
= f.show_if(:category, 'Member Only') do
|
17
17
|
.alert.alert-info.mb-4
|
@@ -1,33 +1,52 @@
|
|
1
|
-
.
|
2
|
-
.
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
1
|
+
.event-registrant-user-fields
|
2
|
+
- user_klass = (f.object.user || current_user).class
|
3
|
+
- ajax_url = (effective_events.users_event_registrants_select2_ajax_index_path unless Rails.env.test?)
|
4
|
+
- disabled = (f.object.user.present? && f.object.user.persisted? && f.object.user.errors.blank?)
|
5
|
+
- event_ticket = f.object.event_ticket
|
6
|
+
|
7
|
+
= f.hidden_field :user_type, value: user_klass.name
|
8
|
+
|
9
|
+
= f.select :user_id, user_klass.all, ajax_url: ajax_url, label: "Quick add", placeholder: "Search by name, email, or company",
|
10
|
+
hint: "Can't find someone? Add their details below.", input_js: { minimumInputLength: 1 }, 'data-event-registrant-user-search': true
|
11
|
+
|
12
|
+
.row
|
13
|
+
.col-md= f.text_field :first_name, input_html: { disabled: disabled }
|
14
|
+
.col-md= f.text_field :last_name, input_html: { disabled: disabled }
|
15
|
+
|
16
|
+
.row
|
17
|
+
.col-md= f.email_field :email, input_html: { disabled: disabled }
|
18
|
+
.col-md
|
19
|
+
= f.hidden_field :organization_type
|
20
|
+
= f.hidden_field :organization_id
|
21
|
+
|
22
|
+
- if EffectiveEvents.organization_enabled? == false
|
23
|
+
= f.text_field :company, input_html: { disabled: disabled }
|
24
|
+
|
25
|
+
- if EffectiveEvents.organization_enabled?
|
26
|
+
= f.hidden_field :organization_type, value: EffectiveMemberships.Organization.name
|
27
|
+
|
28
|
+
- organizations = EffectiveMemberships.Organization.sorted.all
|
29
|
+
|
30
|
+
- if event_ticket&.member_only?
|
31
|
+
- organization_id = (f.object.event_registration&.owner || current_user).try(:organizations).try(:first).try(:id)
|
32
|
+
|
33
|
+
= f.select :organization_id, organizations, label: organization_label, placeholder: 'Search by name', input_html: { disabled: disabled },
|
34
|
+
input_js: { minimumInputLength: 1 },
|
35
|
+
hint: "You can only add new members to your own #{organization_label.downcase}",
|
36
|
+
value: (organization_id if organization_id && f.object.organization_id.blank?)
|
17
37
|
- else
|
18
|
-
|
38
|
+
- # This creates a select field organization_id and a text field company
|
39
|
+
= f.select_or_text :organization_id, :company, organizations, name: organization_label.downcase, input_html: { disabled: disabled },
|
40
|
+
text: { label: "#{organization_label} name", placeholder: "New #{organization_label.downcase} name" },
|
41
|
+
select: { label: organization_label, placeholder: 'Search by name', input_js: { minimumInputLength: 1 } }
|
19
42
|
|
20
|
-
|
21
|
-
|
43
|
+
- if event_ticket.present?
|
44
|
+
- if event_ticket.question1.present?
|
45
|
+
= f.text_field :response1, label: event_ticket.question1
|
22
46
|
|
23
|
-
|
24
|
-
|
25
|
-
- elsif ticket.member_only?
|
26
|
-
= render('effective/event_registrants/fields_member_only', f: f)
|
27
|
-
- elsif ticket.member_or_non_member?
|
28
|
-
= render('effective/event_registrants/fields_member_or_non_member', f: f)
|
29
|
-
- else
|
30
|
-
- raise("Unexpected ticket category: #{ticket.category || 'nil'}")
|
47
|
+
- if event_ticket.question2.present?
|
48
|
+
= f.text_field :response2, label: event_ticket.question2
|
31
49
|
|
32
|
-
|
50
|
+
- if event_ticket.question3.present?
|
51
|
+
= f.text_field :response3, label: event_ticket.question3
|
33
52
|
|
@@ -0,0 +1 @@
|
|
1
|
+
-# Intentionally blank
|
@@ -0,0 +1,26 @@
|
|
1
|
+
- # Displayed on the details step
|
2
|
+
- event = form.object.event
|
3
|
+
|
4
|
+
- form.object.event_registrants.each_with_index do |event_registrant, index|
|
5
|
+
= card("Ticket ##{index+1}") do
|
6
|
+
- event_ticket = event_registrant.event_ticket
|
7
|
+
|
8
|
+
%p
|
9
|
+
= event_ticket
|
10
|
+
= ' - '
|
11
|
+
|
12
|
+
- if event_ticket.member_or_non_member? && event_registrant.first_name.blank? && !event.early_bird?
|
13
|
+
= effective_events_ticket_price(event, event_ticket)
|
14
|
+
- else
|
15
|
+
= price_to_currency(event_registrant.price)
|
16
|
+
|
17
|
+
= event_registrant.details
|
18
|
+
|
19
|
+
= form.fields_for :event_registrants, event_registrant do |fr|
|
20
|
+
- if event.allow_blank_registrants? && (fr.object.user.blank? || fr.object.blank_registrant?)
|
21
|
+
= fr.check_box :blank_registrant, label: "I will return and add this ticket's information later"
|
22
|
+
- else
|
23
|
+
= fr.hidden_field :blank_registrant, value: false
|
24
|
+
|
25
|
+
= fr.show_if(:blank_registrant, false) do
|
26
|
+
= render('effective/event_registrants/fields', f: fr)
|
@@ -0,0 +1,85 @@
|
|
1
|
+
-# Displayed on the tickets step
|
2
|
+
- event = form.object.event
|
3
|
+
- tickets = event.event_tickets.reject(&:archived?)
|
4
|
+
- waitlist = tickets.any? { |ticket| ticket.waitlist? }
|
5
|
+
|
6
|
+
- all_member_only_tickets = tickets.all? { |ticket| ticket.member_only? }
|
7
|
+
- any_member_only_tickets = tickets.any? { |ticket| ticket.member_only? }
|
8
|
+
- is_member = current_user.try(:is?, :member)
|
9
|
+
|
10
|
+
- if event.early_bird?
|
11
|
+
.alert.alert-warning.mb-3
|
12
|
+
Early Bird rates end on
|
13
|
+
= event.early_bird_end_at.strftime("%A, %B %d, %Y at %l:%M%P.")
|
14
|
+
|
15
|
+
%table.table.table-sm.table-striped
|
16
|
+
%thead
|
17
|
+
%tr
|
18
|
+
%th Ticket
|
19
|
+
%th Price
|
20
|
+
%th Quantity
|
21
|
+
|
22
|
+
%tbody
|
23
|
+
- tickets.each do |ticket|
|
24
|
+
%tr
|
25
|
+
%td
|
26
|
+
= ticket.to_s
|
27
|
+
- if ticket.capacity.present? && ticket.display_capacity?
|
28
|
+
%br
|
29
|
+
%small
|
30
|
+
#{event.capacity_available(event_ticket: ticket, event_registration: form.object)} remaining
|
31
|
+
- if ticket.waitlist?
|
32
|
+
before waitlist
|
33
|
+
%td
|
34
|
+
%ul.list-unstyled.mb-0
|
35
|
+
- # Early Bird
|
36
|
+
- if event.early_bird? && ticket.early_bird_price.to_i > 0 && [ticket.member_price, ticket.regular_price].exclude?(ticket.early_bird_price)
|
37
|
+
%li
|
38
|
+
- if ticket.regular_price.to_i > 0
|
39
|
+
%div
|
40
|
+
%s.text-muted
|
41
|
+
= price_to_currency(ticket.regular_price)
|
42
|
+
|
43
|
+
- if ticket.member_price.to_i > 0
|
44
|
+
%div
|
45
|
+
%s.text-muted
|
46
|
+
= price_to_currency(ticket.member_price)
|
47
|
+
.badge.badge-secondary.mr-2 Members
|
48
|
+
|
49
|
+
%div
|
50
|
+
= price_to_currency(ticket.early_bird_price)
|
51
|
+
.badge.badge-warning Early Bird
|
52
|
+
- else
|
53
|
+
- if ticket.regular_price.present?
|
54
|
+
%li
|
55
|
+
= price_to_currency(ticket.regular_price)
|
56
|
+
|
57
|
+
- if ticket.member_price.present?
|
58
|
+
%li
|
59
|
+
= price_to_currency(ticket.member_price)
|
60
|
+
.badge.badge-secondary Members
|
61
|
+
|
62
|
+
%td
|
63
|
+
- event_ticket_selection = form.object.event_ticket_selection(event_ticket: ticket)
|
64
|
+
|
65
|
+
= form.fields_for :event_ticket_selections, event_ticket_selection do |f|
|
66
|
+
= f.hidden_field :event_ticket_id
|
67
|
+
= f.hidden_field :quantity, value: 0
|
68
|
+
|
69
|
+
- capacity = event.capacity_selectable(event_ticket: ticket, event_registration: form.object)
|
70
|
+
- disabled = (ticket.member_only? && !is_member)
|
71
|
+
|
72
|
+
- if form.object.selected_expired? && !f.object.errors.present?
|
73
|
+
- f.object.assign_attributes(quantity: 0)
|
74
|
+
|
75
|
+
= f.select :quantity, (0..capacity), label: false, disabled: disabled,
|
76
|
+
include_blank: false, input_js: { minimumResultsForSearch: 'Infinity' }
|
77
|
+
|
78
|
+
- if waitlist
|
79
|
+
%p If the ticket capacity has been reached you will be added to the waitlist.
|
80
|
+
|
81
|
+
- unless is_member
|
82
|
+
- if all_member_only_tickets
|
83
|
+
.alert.alert-info.mb-4 You must be a member to purchase tickets.
|
84
|
+
- elsif any_member_only_tickets
|
85
|
+
.alert.alert-info.mb-4 You must be a member to purchase some of these tickets.
|