effective_events 0.13.1 → 0.14.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/controllers/admin/event_addons_controller.rb +1 -1
- data/app/controllers/admin/event_registrants_controller.rb +1 -1
- data/app/datatables/admin/effective_event_addons_datatable.rb +2 -1
- data/app/datatables/admin/effective_event_registrants_datatable.rb +34 -5
- data/app/datatables/admin/effective_event_registrations_datatable.rb +3 -2
- data/app/datatables/admin/effective_event_tickets_datatable.rb +1 -0
- data/app/datatables/effective_event_registrants_datatable.rb +6 -2
- data/app/helpers/effective_events_helper.rb +2 -3
- data/app/models/concerns/effective_events_event_registration.rb +46 -3
- data/app/models/effective/event.rb +9 -4
- data/app/models/effective/event_addon.rb +7 -3
- data/app/models/effective/event_registrant.rb +70 -13
- data/app/models/effective/event_ticket.rb +31 -2
- data/app/views/admin/event_addons/_form.html.haml +1 -1
- data/app/views/admin/event_registrants/_form.html.haml +3 -1
- data/app/views/admin/event_tickets/_form.html.haml +28 -21
- data/app/views/effective/event_registrations/_event_tickets.html.haml +43 -0
- data/app/views/effective/event_registrations/_form_blank_registrants.html.haml +1 -1
- data/app/views/effective/event_registrations/addons.html.haml +8 -10
- data/app/views/effective/event_registrations/checkout.html.haml +3 -3
- data/app/views/effective/event_registrations/submitted.html.haml +5 -1
- data/app/views/effective/event_registrations/summary.html.haml +1 -1
- data/app/views/effective/event_registrations/tickets.html.haml +13 -10
- data/config/locales/effective_events.en.yml +13 -0
- data/config/routes.rb +3 -0
- data/db/migrate/101_create_effective_events.rb +6 -0
- data/lib/effective_events/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d25eaee6089c0b76752550e6458c502124947d0e244a1d0e7b65584935caa43
|
4
|
+
data.tar.gz: 6b06663b84f26a0ba07324fe601c41bc7070117c42e019527ecffbcbcc0fcd6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c599c5411f8c66a3dbe6f4c0ded8f9ef6f202c25d66cbdee33ee141cbbd3d4afd1fbd4a19ae55ccc9fc303a44882b5c971359595b31e30f551e5f35ed3b4f13b
|
7
|
+
data.tar.gz: 77ac6e934e9276331670d270dee9d82b55bf2eb8c2e1ed90ee57a9b1798aa56bcca6142d46dcb98b140adc1dbf61982ff469b9c2950c62a9a7252a0813d08272
|
@@ -4,6 +4,7 @@ module Admin
|
|
4
4
|
scope :unarchived, label: "All"
|
5
5
|
scope :purchased
|
6
6
|
scope :deferred
|
7
|
+
scope :not_purchased
|
7
8
|
scope :archived
|
8
9
|
end
|
9
10
|
|
@@ -35,7 +36,7 @@ module Admin
|
|
35
36
|
end
|
36
37
|
|
37
38
|
collection do
|
38
|
-
scope = Effective::EventAddon.deep.
|
39
|
+
scope = Effective::EventAddon.deep.registered.includes(:purchased_order, :owner)
|
39
40
|
|
40
41
|
if attributes[:event_id].present?
|
41
42
|
scope = scope.where(event: event)
|
@@ -4,15 +4,20 @@ module Admin
|
|
4
4
|
scope :unarchived, label: "All"
|
5
5
|
scope :purchased
|
6
6
|
scope :deferred
|
7
|
+
scope :not_purchased
|
7
8
|
scope :archived
|
8
9
|
end
|
9
10
|
|
10
11
|
datatable do
|
12
|
+
order :registered_at, :asc
|
13
|
+
|
11
14
|
col :updated_at, visible: false
|
12
15
|
col :created_at, visible: false
|
13
16
|
col :id, visible: false
|
14
17
|
col :archived, visible: false
|
15
18
|
|
19
|
+
col :registered_at
|
20
|
+
|
16
21
|
col :event
|
17
22
|
|
18
23
|
col :owner, visible: false
|
@@ -24,12 +29,36 @@ module Admin
|
|
24
29
|
col :event_ticket, search: :string
|
25
30
|
end
|
26
31
|
|
27
|
-
col :
|
32
|
+
col :waitlisted do |registrant|
|
33
|
+
if registrant.promoted?
|
34
|
+
'Promoted'
|
35
|
+
elsif registrant.waitlisted?
|
36
|
+
'Waitlisted'
|
37
|
+
else
|
38
|
+
'-'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
col :promoted, visible: false
|
28
43
|
|
44
|
+
col :name do |er|
|
45
|
+
if er.first_name.present?
|
46
|
+
"#{er.first_name} #{er.last_name}<br><small>#{mail_to(er.email)}</small>"
|
47
|
+
elsif er.owner.present?
|
48
|
+
er.owner.to_s + ' - GUEST'
|
49
|
+
else
|
50
|
+
'Unknown'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
29
54
|
col :user, label: 'Member'
|
30
|
-
|
31
|
-
col :
|
32
|
-
col :
|
55
|
+
|
56
|
+
col :orders, visible: false
|
57
|
+
col :price, as: :price
|
58
|
+
|
59
|
+
col :first_name, visible: false
|
60
|
+
col :last_name, visible: false
|
61
|
+
col :email, visible: false
|
33
62
|
col :company, visible: false
|
34
63
|
|
35
64
|
col :response1
|
@@ -40,7 +69,7 @@ module Admin
|
|
40
69
|
end
|
41
70
|
|
42
71
|
collection do
|
43
|
-
scope = Effective::EventRegistrant.deep.
|
72
|
+
scope = Effective::EventRegistrant.deep.registered
|
44
73
|
|
45
74
|
if attributes[:event_id].present?
|
46
75
|
scope = scope.where(event: event)
|
@@ -7,7 +7,8 @@ class Admin::EffectiveEventRegistrationsDatatable < Effective::Datatable
|
|
7
7
|
col :created_at, label: 'Created', visible: false
|
8
8
|
col :updated_at, label: 'Updated', visible: false
|
9
9
|
|
10
|
-
col :submitted_at, label: 'Submitted',
|
10
|
+
col :submitted_at, label: 'Submitted', as: :date
|
11
|
+
col :completed_at, label: 'Completed', as: :date
|
11
12
|
|
12
13
|
col :event, search: :string
|
13
14
|
col :owner
|
@@ -20,7 +21,7 @@ class Admin::EffectiveEventRegistrationsDatatable < Effective::Datatable
|
|
20
21
|
end
|
21
22
|
|
22
23
|
collection do
|
23
|
-
EffectiveEvents.EventRegistration.all.deep.
|
24
|
+
EffectiveEvents.EventRegistration.all.deep.where.not(status: :draft)
|
24
25
|
end
|
25
26
|
|
26
27
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
class EffectiveEventRegistrantsDatatable < Effective::Datatable
|
4
4
|
datatable do
|
5
|
+
order :id
|
5
6
|
|
6
7
|
col :name do |er|
|
7
8
|
if er.first_name.present?
|
@@ -13,9 +14,12 @@ class EffectiveEventRegistrantsDatatable < Effective::Datatable
|
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
17
|
+
col :id, visible: false
|
18
|
+
|
16
19
|
col :event_ticket, search: :string, label: 'Ticket' do |er|
|
17
20
|
[
|
18
21
|
er.event_ticket.to_s,
|
22
|
+
(content_tag(:span, 'Waitlist', class: 'badge badge-warning') if er.waitlisted_not_promoted?),
|
19
23
|
(content_tag(:span, 'Archived', class: 'badge badge-warning') if er.event_ticket&.archived?)
|
20
24
|
].compact.join('<br>').html_safe
|
21
25
|
end
|
@@ -36,8 +40,8 @@ class EffectiveEventRegistrantsDatatable < Effective::Datatable
|
|
36
40
|
end.join.html_safe
|
37
41
|
end
|
38
42
|
|
39
|
-
|
40
|
-
|
43
|
+
# This is the non-waitlisted full price
|
44
|
+
col :event_ticket_price, as: :price, label: 'Price'
|
41
45
|
col :archived, visible: false
|
42
46
|
|
43
47
|
# no actions_col
|
@@ -38,10 +38,9 @@ module EffectiveEventsHelper
|
|
38
38
|
title = ticket.to_s
|
39
39
|
price = effective_events_ticket_price(event, ticket)
|
40
40
|
|
41
|
-
|
41
|
+
label = [title, price].compact.join(' - ')
|
42
42
|
|
43
|
-
|
44
|
-
disabled = { disabled: :disabled } unless (authorized || event.event_ticket_available?(ticket, quantity: 1))
|
43
|
+
disabled = { disabled: :disabled } unless (authorized || ticket.waitlist? || event.event_ticket_available?(ticket, quantity: 1))
|
45
44
|
|
46
45
|
[label, ticket.to_param, disabled].compact
|
47
46
|
end
|
@@ -18,6 +18,9 @@ module EffectiveEventsEventRegistration
|
|
18
18
|
end
|
19
19
|
|
20
20
|
included do
|
21
|
+
# Needs to be first up here. Before the acts_as_purchasable_parent one voids the order
|
22
|
+
around_destroy :around_destroy_deferred_event_registration, if: -> { submit_order&.deferred? }
|
23
|
+
|
21
24
|
acts_as_purchasable_parent
|
22
25
|
acts_as_tokened
|
23
26
|
|
@@ -128,6 +131,15 @@ module EffectiveEventsEventRegistration
|
|
128
131
|
# If we're submitted. Try to move to completed.
|
129
132
|
before_save(if: -> { submitted? }) { try_completed! }
|
130
133
|
|
134
|
+
def around_destroy_deferred_event_registration
|
135
|
+
raise('expecting a deferred submit order') unless submit_order&.deferred?
|
136
|
+
|
137
|
+
waitlisted_event_tickets_was = event_tickets().select(&:waitlist?)
|
138
|
+
yield
|
139
|
+
waitlisted_event_tickets_was.each { |event_ticket| event_ticket.update_waitlist! }
|
140
|
+
true
|
141
|
+
end
|
142
|
+
|
131
143
|
def delayed_payment_date_upcoming?
|
132
144
|
event&.delayed_payment_date_upcoming?
|
133
145
|
end
|
@@ -180,7 +192,13 @@ module EffectiveEventsEventRegistration
|
|
180
192
|
true
|
181
193
|
end
|
182
194
|
|
195
|
+
def after_submit_deferred!
|
196
|
+
update_deferred_event_registration!
|
197
|
+
end
|
198
|
+
|
183
199
|
def after_submit_purchased!
|
200
|
+
event_registrants.each { |event_registrant| event_registrant.registered! }
|
201
|
+
|
184
202
|
notifications = event.event_notifications.select(&:registrant_purchased?)
|
185
203
|
notifications.each { |notification| notification.notify!(event_registrants: event_registrants) }
|
186
204
|
end
|
@@ -200,12 +218,19 @@ module EffectiveEventsEventRegistration
|
|
200
218
|
end
|
201
219
|
|
202
220
|
def tickets!
|
203
|
-
after_commit
|
221
|
+
after_commit do
|
222
|
+
update_submit_fees_and_order! if submit_order.present?
|
223
|
+
update_deferred_event_registration! if submit_order&.deferred?
|
224
|
+
end
|
225
|
+
|
204
226
|
save!
|
205
227
|
end
|
206
228
|
|
207
229
|
def addons!
|
208
|
-
after_commit
|
230
|
+
after_commit do
|
231
|
+
update_submit_fees_and_order! if submit_order.present?
|
232
|
+
end
|
233
|
+
|
209
234
|
save!
|
210
235
|
end
|
211
236
|
|
@@ -265,11 +290,17 @@ module EffectiveEventsEventRegistration
|
|
265
290
|
event_addons
|
266
291
|
end
|
267
292
|
|
293
|
+
def event_tickets
|
294
|
+
present_event_registrants.map(&:event_ticket).uniq
|
295
|
+
end
|
296
|
+
|
268
297
|
def unavailable_event_tickets
|
269
298
|
unavailable = []
|
270
299
|
|
271
300
|
present_event_registrants.map(&:event_ticket).group_by { |t| t }.each do |event_ticket, event_tickets|
|
272
|
-
|
301
|
+
unless event_ticket.waitlist? || event.event_ticket_available?(event_ticket, quantity: event_tickets.length)
|
302
|
+
unavailable << event_ticket
|
303
|
+
end
|
273
304
|
end
|
274
305
|
|
275
306
|
unavailable
|
@@ -317,6 +348,18 @@ module EffectiveEventsEventRegistration
|
|
317
348
|
|
318
349
|
private
|
319
350
|
|
351
|
+
def update_deferred_event_registration!
|
352
|
+
raise('expected a deferred submit order') unless submit_order&.deferred?
|
353
|
+
|
354
|
+
# Mark registered anyone who hasn't been registered yet. They are now!
|
355
|
+
event_registrants.reject(&:registered?).each { |event_registrant| event_registrant.registered! }
|
356
|
+
|
357
|
+
# Update the waitlist for any event tickets
|
358
|
+
event_tickets.select(&:waitlist?).each { |event_ticket| event_ticket.update_waitlist! }
|
359
|
+
|
360
|
+
true
|
361
|
+
end
|
362
|
+
|
320
363
|
def present_event_registrants
|
321
364
|
event_registrants.reject(&:marked_for_destruction?).reject(&:archived?)
|
322
365
|
end
|
@@ -15,18 +15,18 @@ module Effective
|
|
15
15
|
has_many :event_products, -> { EventProduct.sorted }, inverse_of: :event, dependent: :destroy
|
16
16
|
accepts_nested_attributes_for :event_products, allow_destroy: true
|
17
17
|
|
18
|
-
has_many :event_registrants, -> { order(:event_ticket_id
|
18
|
+
has_many :event_registrants, -> { order(:event_ticket_id).order(:id) }, inverse_of: :event
|
19
19
|
accepts_nested_attributes_for :event_registrants, allow_destroy: true
|
20
20
|
|
21
|
-
has_many :event_addons, -> { order(:event_product_id
|
21
|
+
has_many :event_addons, -> { order(:event_product_id).order(:id) }, inverse_of: :event
|
22
22
|
accepts_nested_attributes_for :event_addons, allow_destroy: true
|
23
23
|
|
24
24
|
has_many :event_notifications, -> { order(:id) }, inverse_of: :event, dependent: :destroy
|
25
25
|
accepts_nested_attributes_for :event_notifications, allow_destroy: true
|
26
26
|
|
27
27
|
# Used by the registration_available checks
|
28
|
-
has_many :registered_event_registrants, -> { EventRegistrant.registered }, class_name: 'Effective::EventRegistrant', inverse_of: :event
|
29
|
-
has_many :registered_event_addons, -> { EventAddon.registered }, class_name: 'Effective::EventAddon', inverse_of: :event
|
28
|
+
has_many :registered_event_registrants, -> { EventRegistrant.registered.unarchived }, class_name: 'Effective::EventRegistrant', inverse_of: :event
|
29
|
+
has_many :registered_event_addons, -> { EventAddon.registered.unarchived }, class_name: 'Effective::EventAddon', inverse_of: :event
|
30
30
|
|
31
31
|
# rich_text_body - Used by the select step
|
32
32
|
has_many_rich_texts
|
@@ -192,6 +192,10 @@ module Effective
|
|
192
192
|
rich_text_excerpt
|
193
193
|
end
|
194
194
|
|
195
|
+
def any_waitlist?
|
196
|
+
event_tickets.any? { |et| et.waitlist? }
|
197
|
+
end
|
198
|
+
|
195
199
|
def published?
|
196
200
|
return false if draft?
|
197
201
|
return false if published_at.blank?
|
@@ -214,6 +218,7 @@ module Effective
|
|
214
218
|
|
215
219
|
def sold_out?
|
216
220
|
return false unless event_tickets.present?
|
221
|
+
return false if any_waitlist?
|
217
222
|
event_tickets.none? { |event_ticket| event_ticket_available?(event_ticket, quantity: 1) }
|
218
223
|
end
|
219
224
|
|
@@ -42,7 +42,7 @@ module Effective
|
|
42
42
|
|
43
43
|
scope :sorted, -> { order(:id) }
|
44
44
|
scope :deep, -> { includes(:event, :event_product) }
|
45
|
-
scope :registered, -> { purchased_or_deferred
|
45
|
+
scope :registered, -> { purchased_or_deferred }
|
46
46
|
|
47
47
|
before_validation(if: -> { event_registration.present? }) do
|
48
48
|
self.event ||= event_registration.event
|
@@ -84,8 +84,12 @@ module Effective
|
|
84
84
|
event_product.qb_item_name
|
85
85
|
end
|
86
86
|
|
87
|
-
|
88
|
-
|
87
|
+
def registered?
|
88
|
+
purchased_or_deferred?
|
89
|
+
end
|
90
|
+
|
91
|
+
# This is the Admin Save and Mark Registered historic action
|
92
|
+
def mark_registered!
|
89
93
|
raise('expected a blank event registration') if event_registration.present?
|
90
94
|
|
91
95
|
save!
|
@@ -34,6 +34,10 @@ module Effective
|
|
34
34
|
blank_registrant :boolean
|
35
35
|
member_registrant :boolean
|
36
36
|
|
37
|
+
waitlisted :boolean
|
38
|
+
promoted :boolean # An admin marked this registrant as promoted from the waitlist
|
39
|
+
registered_at :datetime # When the order is deferred or purchased
|
40
|
+
|
37
41
|
# Question Responses
|
38
42
|
question1 :text
|
39
43
|
question2 :text
|
@@ -54,8 +58,10 @@ module Effective
|
|
54
58
|
end
|
55
59
|
|
56
60
|
scope :sorted, -> { order(:last_name) }
|
57
|
-
scope :deep, -> { includes(:event, :event_ticket) }
|
58
|
-
|
61
|
+
scope :deep, -> { includes(:event, :event_ticket, :owner) }
|
62
|
+
|
63
|
+
#scope :registered, -> { purchased_or_deferred.unarchived }
|
64
|
+
scope :registered, -> { where.not(registered_at: nil) }
|
59
65
|
|
60
66
|
before_validation(if: -> { event_registration.present? }) do
|
61
67
|
self.event ||= event_registration.event
|
@@ -74,6 +80,10 @@ module Effective
|
|
74
80
|
assign_price()
|
75
81
|
end
|
76
82
|
|
83
|
+
validate(if: -> { event_ticket.present? }, unless: -> { purchased? }) do
|
84
|
+
errors.add(:waitlisted, 'is not permitted for a non-waitlist event ticket') if waitlisted? && !event_ticket.waitlist?
|
85
|
+
end
|
86
|
+
|
77
87
|
validates :user_id, uniqueness: { scope: [:event_id], allow_blank: true, message: 'is already registered for this event' }
|
78
88
|
validates :price, presence: true, numericality: { greater_than_or_equal_to: 0 }
|
79
89
|
validates :email, email: true
|
@@ -97,16 +107,30 @@ module Effective
|
|
97
107
|
validates :email, presence: true, unless: -> { user.present? }
|
98
108
|
end
|
99
109
|
|
110
|
+
after_defer do
|
111
|
+
registered! if event_registration.blank? && !registered?
|
112
|
+
end
|
113
|
+
|
114
|
+
after_purchase do
|
115
|
+
registered! if event_registration.blank? && !registered?
|
116
|
+
end
|
117
|
+
|
100
118
|
def to_s
|
101
119
|
persisted? ? title : 'registrant'
|
102
120
|
end
|
103
121
|
|
104
122
|
def title
|
105
|
-
|
123
|
+
[event_ticket.to_s, name, ('WAITLIST' if waitlisted_not_promoted?)].compact.join(' - ')
|
106
124
|
end
|
107
125
|
|
108
126
|
def name
|
109
|
-
first_name.present?
|
127
|
+
if first_name.present?
|
128
|
+
"#{first_name} #{last_name}"
|
129
|
+
elsif owner.present?
|
130
|
+
owner.to_s + ' - GUEST'
|
131
|
+
else
|
132
|
+
'GUEST'
|
133
|
+
end
|
110
134
|
end
|
111
135
|
|
112
136
|
def last_first_name
|
@@ -125,27 +149,48 @@ module Effective
|
|
125
149
|
event_ticket&.qb_item_name
|
126
150
|
end
|
127
151
|
|
128
|
-
|
129
|
-
|
130
|
-
|
152
|
+
def registered?
|
153
|
+
registered_at.present?
|
154
|
+
end
|
131
155
|
|
156
|
+
# Called by an event_registration after_defer and after_purchase
|
157
|
+
def registered!
|
158
|
+
self.registered_at ||= Time.zone.now
|
132
159
|
save!
|
160
|
+
end
|
133
161
|
|
134
|
-
|
135
|
-
|
162
|
+
# This is the Admin Save and Mark Registered action
|
163
|
+
def mark_registered!
|
164
|
+
registered!
|
165
|
+
end
|
166
|
+
|
167
|
+
def promote!
|
168
|
+
raise('expected a waitlist? event_ticket') unless event_ticket.waitlist?
|
169
|
+
|
170
|
+
update!(promoted: true)
|
171
|
+
orders.reject(&:purchased?).each { |order| order.update_purchasable_attributes! }
|
136
172
|
|
137
173
|
true
|
138
174
|
end
|
139
175
|
|
140
|
-
|
176
|
+
def unpromote!
|
177
|
+
raise('expected a waitlist? event_ticket') unless event_ticket.waitlist?
|
141
178
|
|
142
|
-
|
143
|
-
|
179
|
+
update!(promoted: false)
|
180
|
+
orders.reject(&:purchased?).each { |order| order.update_purchasable_attributes! }
|
181
|
+
|
182
|
+
true
|
183
|
+
end
|
184
|
+
|
185
|
+
def registered?
|
186
|
+
registered_at.present?
|
187
|
+
end
|
144
188
|
|
189
|
+
def event_ticket_price
|
145
190
|
raise('expected an event') if event.blank?
|
146
191
|
raise('expected an event ticket') if event_ticket.blank?
|
147
192
|
|
148
|
-
|
193
|
+
if event.early_bird?
|
149
194
|
event_ticket.early_bird_price # Early Bird Pricing
|
150
195
|
elsif event_ticket.regular?
|
151
196
|
event_ticket.regular_price
|
@@ -156,6 +201,18 @@ module Effective
|
|
156
201
|
else
|
157
202
|
raise("Unexpected event ticket price calculation")
|
158
203
|
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def waitlisted_not_promoted?
|
207
|
+
(waitlisted? && !promoted?)
|
208
|
+
end
|
209
|
+
|
210
|
+
private
|
211
|
+
|
212
|
+
def assign_price
|
213
|
+
raise('is already purchased') if purchased?
|
214
|
+
|
215
|
+
price = waitlisted_not_promoted? ? 0 : event_ticket_price
|
159
216
|
|
160
217
|
assign_attributes(price: price)
|
161
218
|
end
|
@@ -8,9 +8,11 @@ module Effective
|
|
8
8
|
|
9
9
|
belongs_to :event
|
10
10
|
|
11
|
-
has_many :event_registrants
|
11
|
+
has_many :event_registrants, -> { order(:id) }, inverse_of: :event_ticket
|
12
|
+
accepts_nested_attributes_for :event_registrants
|
13
|
+
|
12
14
|
has_many :purchased_event_registrants, -> { EventRegistrant.purchased.unarchived }, class_name: 'Effective::EventRegistrant'
|
13
|
-
has_many :registered_event_registrants, -> { EventRegistrant.registered.unarchived }, class_name: 'Effective::EventRegistrant'
|
15
|
+
has_many :registered_event_registrants, -> { EventRegistrant.registered.unarchived.order(:registered_at).order(:id) }, class_name: 'Effective::EventRegistrant'
|
14
16
|
|
15
17
|
log_changes(to: :event) if respond_to?(:log_changes)
|
16
18
|
|
@@ -20,7 +22,9 @@ module Effective
|
|
20
22
|
|
21
23
|
effective_resource do
|
22
24
|
title :string
|
25
|
+
|
23
26
|
capacity :integer
|
27
|
+
waitlist :boolean
|
24
28
|
|
25
29
|
category :string
|
26
30
|
|
@@ -63,10 +67,34 @@ module Effective
|
|
63
67
|
validates :early_bird_price, presence: true, if: -> { event&.early_bird_end_at.present? }
|
64
68
|
validates :early_bird_price, numericality: { greater_than_or_equal_to: 0, allow_blank: true }
|
65
69
|
|
70
|
+
validates :capacity, numericality: { greater_than_or_equal_to: 0, allow_blank: true }
|
71
|
+
validates :capacity, numericality: { greater_than_or_equal_to: 1, message: 'must have a non-zero capacity when using waitlist' }, if: -> { waitlist? }
|
72
|
+
|
66
73
|
def to_s
|
67
74
|
title.presence || 'New Event Ticket'
|
68
75
|
end
|
69
76
|
|
77
|
+
# This is supposed to be an indempotent big update the world thing
|
78
|
+
def update_waitlist!
|
79
|
+
return false unless waitlist?
|
80
|
+
|
81
|
+
changed_event_registrants = registered_event_registrants.each_with_index.map do |event_registrant, index|
|
82
|
+
next if event_registrant.purchased?
|
83
|
+
|
84
|
+
waitlisted_was = event_registrant.waitlisted?
|
85
|
+
waitlisted = (waitlist? && index >= capacity)
|
86
|
+
next if waitlisted == waitlisted_was
|
87
|
+
|
88
|
+
event_registrant.update!(waitlisted: waitlisted) # Updates price
|
89
|
+
event_registrant
|
90
|
+
end.compact
|
91
|
+
|
92
|
+
orders = changed_event_registrants.flat_map { |event_registrant| event_registrant.deferred_orders }.compact.uniq
|
93
|
+
orders.each { |order| order.update_purchasable_attributes! }
|
94
|
+
|
95
|
+
true
|
96
|
+
end
|
97
|
+
|
70
98
|
def capacity_available
|
71
99
|
return nil if capacity.blank?
|
72
100
|
[(capacity - registered_event_registrants_count), 0].max
|
@@ -95,5 +123,6 @@ module Effective
|
|
95
123
|
def member_or_non_member?
|
96
124
|
category == 'Member or Non-Member'
|
97
125
|
end
|
126
|
+
|
98
127
|
end
|
99
128
|
end
|
@@ -11,11 +11,13 @@
|
|
11
11
|
- else
|
12
12
|
= f.static_field :owner
|
13
13
|
|
14
|
+
= f.datetime_field :registered_at
|
15
|
+
|
14
16
|
= render 'effective/event_registrants/fields', f: f, event: event_registrant.event, namespace: :admin
|
15
17
|
|
16
18
|
= f.check_box :archived, label: "Archive this registrant. It will be displayed as archived on the owner's event registration"
|
17
19
|
|
18
20
|
- if f.object.new_record?
|
19
|
-
= f.submit 'Save and Mark
|
21
|
+
= f.submit 'Save and Mark Registered'
|
20
22
|
- else
|
21
23
|
= f.submit 'Save'
|
@@ -5,25 +5,32 @@
|
|
5
5
|
= f.text_field :title
|
6
6
|
|
7
7
|
.row
|
8
|
-
.col
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
8
|
+
.col
|
9
|
+
= f.select :category, Effective::EventTicket::CATEGORIES, hint: "Determines who can purchase this ticket at which price. Also determines if the dropdown of related members is displayed to the purchaser."
|
10
|
+
|
11
|
+
= f.show_if(:category, 'Regular') do
|
12
|
+
.alert.alert-info.mb-4
|
13
|
+
%strong Regular Ticket:
|
14
|
+
Anyone will be able to purchase this ticket. They will be asked for a first name, last name and email. Will not display the dropdown list of related members. Only the regular price applies.
|
15
|
+
|
16
|
+
= f.show_if(:category, 'Member Only') do
|
17
|
+
.alert.alert-info.mb-4
|
18
|
+
%strong Member Only Ticket:
|
19
|
+
Only members will be able to purchase this ticket. They must select a member from the dropdown list of related members. Only the member price applies.
|
20
|
+
|
21
|
+
= f.show_if(:category, 'Member or Non-Member') do
|
22
|
+
.alert.alert-info.mb-4
|
23
|
+
%strong Member or Non-Member Ticket:
|
24
|
+
Anyone will be able to purchase this ticket. They can select a member from the dropdown list of related members to receive the member pricing.
|
25
|
+
Or, they can enter a first name, last name and email to receive the regular pricing.
|
26
|
+
|
27
|
+
.col
|
28
|
+
= f.number_field :capacity, hint: "The number of registrations will be limited to capacity.<br>Leave blank for unlimited capacity."
|
29
|
+
|
30
|
+
- if f.object.event&.delayed?
|
31
|
+
= f.check_box :waitlist,
|
32
|
+
label: "Yes, add to waitlist once capacity is reached",
|
33
|
+
hint: "requires a delayed payment event. Once capacity is reached, new registrations will be added to the waitlist. Payment information is collected but not charged for waitlisted registrants."
|
27
34
|
.row
|
28
35
|
.col-md-6
|
29
36
|
- if f.object.event&.early_bird_end_at.present?
|
@@ -37,9 +44,9 @@
|
|
37
44
|
|
38
45
|
.row
|
39
46
|
- if defined?(EffectiveQbSync)
|
40
|
-
.col= f.text_field :qb_item_name, label: 'QuickBooks item name'
|
41
|
-
.col= f.check_box :tax_exempt
|
47
|
+
.col-md-6= f.text_field :qb_item_name, label: 'QuickBooks item name'
|
42
48
|
|
49
|
+
= f.check_box :tax_exempt
|
43
50
|
= f.check_box :archived, label: 'Archive this ticket. It will be unavailable for purchase.'
|
44
51
|
|
45
52
|
= card('Questions') do
|
@@ -0,0 +1,43 @@
|
|
1
|
+
.card.mb-4
|
2
|
+
.card-body
|
3
|
+
- tickets = resource.event.event_tickets.reject(&:archived?)
|
4
|
+
|
5
|
+
- member_column = tickets.any? { |ticket| ticket.member_only? || ticket.member_or_non_member? }
|
6
|
+
- waitlist = tickets.any? { |ticket| ticket.waitlist? }
|
7
|
+
|
8
|
+
%p This event has the following tickets available for purchase:
|
9
|
+
|
10
|
+
%table.table
|
11
|
+
%thead
|
12
|
+
%tr
|
13
|
+
%th Ticket
|
14
|
+
- if member_column
|
15
|
+
%th Member Price
|
16
|
+
%th #{'Regualar ' if member_column}Price
|
17
|
+
|
18
|
+
%tbody
|
19
|
+
- tickets.each do |ticket|
|
20
|
+
%tr
|
21
|
+
%td
|
22
|
+
= ticket.to_s
|
23
|
+
- if ticket.capacity.present?
|
24
|
+
%br
|
25
|
+
%small
|
26
|
+
#{ticket.capacity_available} remaining
|
27
|
+
- if ticket.waitlist?
|
28
|
+
before waitlist
|
29
|
+
|
30
|
+
- if member_column
|
31
|
+
%td
|
32
|
+
- if ticket.member_price.present?
|
33
|
+
= price_to_currency(ticket.member_price)
|
34
|
+
- else
|
35
|
+
= '-'
|
36
|
+
%td
|
37
|
+
- if ticket.regular_price.present?
|
38
|
+
= price_to_currency(ticket.regular_price)
|
39
|
+
- else
|
40
|
+
= '-'
|
41
|
+
|
42
|
+
- if waitlist
|
43
|
+
%p If the ticket capacity has been reached you will be added to the waitlist.
|
@@ -8,16 +8,14 @@
|
|
8
8
|
|
9
9
|
= render 'effective/event_registrations/content', resource: resource
|
10
10
|
|
11
|
-
|
12
|
-
.
|
13
|
-
= effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
|
14
|
-
= f.hidden_field :id
|
11
|
+
= effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
|
12
|
+
= f.hidden_field :id
|
15
13
|
|
16
|
-
|
17
|
-
|
14
|
+
= f.has_many :event_addons, f.object.build_event_addons, reorder: false do |fp|
|
15
|
+
= render('effective/event_addons/fields', f: fp, event: f.object.event)
|
18
16
|
|
19
|
-
|
20
|
-
|
17
|
+
- if resource.delayed_payment_date_upcoming? && resource.submit_order&.delayed? && resource.submit_order&.deferred?
|
18
|
+
.alert.alert-info If the price of your registration changes, your order will be automatically updated.
|
21
19
|
|
22
|
-
|
23
|
-
|
20
|
+
%hr
|
21
|
+
= f.save 'Save and Continue'
|
@@ -3,17 +3,17 @@
|
|
3
3
|
|
4
4
|
- if resource.submit_order.deferred?
|
5
5
|
= card do
|
6
|
-
= render_checkout_step2(resource.submit_order, purchased_url: wizard_path(:complete), deferred_url: wizard_path(:submitted), declined_url: wizard_path(:checkout))
|
6
|
+
= render_checkout_step2(resource.submit_order, purchased_url: wizard_path(:complete), deferred_url: wizard_path(:submitted), declined_url: wizard_path(:checkout), skip_order: resource.submit_order.delayed?)
|
7
7
|
- elsif resource.event.registerable? == false
|
8
8
|
.alert.alert-danger Your selected event is no longer available for registration.
|
9
9
|
- elsif resource.unavailable_event_tickets.present?
|
10
10
|
.alert.alert-danger Your selected number of event tickets are no longer available.
|
11
11
|
- elsif resource.unavailable_event_products.present?
|
12
12
|
.alert.alert-danger Your selected number of event add-ons are no longer available.
|
13
|
+
|
13
14
|
- else
|
14
15
|
= card do
|
15
|
-
= render_checkout_step2(resource.submit_order, purchased_url: wizard_path(:complete), deferred_url: wizard_path(:submitted), declined_url: wizard_path(:checkout))
|
16
|
-
|
16
|
+
= render_checkout_step2(resource.submit_order, purchased_url: wizard_path(:complete), deferred_url: wizard_path(:submitted), declined_url: wizard_path(:checkout), skip_order: resource.submit_order.delayed?)
|
17
17
|
|
18
18
|
- if resource.submit_order.delayed? && resource.submit_order.deferred?
|
19
19
|
= link_to 'Save and Continue', wizard_path(:submitted), class: 'btn btn-primary'
|
@@ -22,8 +22,12 @@
|
|
22
22
|
|
23
23
|
= card do
|
24
24
|
%h3 All done
|
25
|
-
%p
|
25
|
+
%p The registration for #{resource.event} has been submitted. You're all done!
|
26
26
|
%p= resource.submit_order.delayed_payment_info
|
27
|
+
|
28
|
+
- if resource.event_registrants.any?(&:waitlisted?)
|
29
|
+
%p Any waitlist tickets are not charged. If you are moved off the waitlist, the full price will be charged.
|
30
|
+
|
27
31
|
%p You can #{link_to('change your registration', wizard_path(:tickets))} until the payment date.
|
28
32
|
|
29
33
|
= render 'effective/event_registrations/event_registration', event_registration: resource
|
@@ -1,16 +1,19 @@
|
|
1
1
|
= render 'layout' do
|
2
|
+
|
3
|
+
= render 'effective/event_registrations/event_tickets', resource: resource
|
4
|
+
|
2
5
|
= render 'effective/event_registrations/content', resource: resource
|
3
6
|
|
4
|
-
|
5
|
-
.
|
6
|
-
|
7
|
-
|
7
|
+
= effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
|
8
|
+
= f.hidden_field :id
|
9
|
+
|
10
|
+
%p Please select one or more tickets to register for this event:
|
8
11
|
|
9
|
-
|
10
|
-
|
12
|
+
= f.has_many :event_registrants, f.object.build_event_registrants, reorder: false do |fr|
|
13
|
+
= render('effective/event_registrants/fields', f: fr, event: f.object.event, namespace: :events)
|
11
14
|
|
12
|
-
|
13
|
-
|
15
|
+
- if resource.delayed_payment_date_upcoming? && resource.submit_order&.delayed? && resource.submit_order&.deferred?
|
16
|
+
.alert.alert-info If the price of your registration changes, your order will be automatically updated.
|
14
17
|
|
15
|
-
|
16
|
-
|
18
|
+
%hr
|
19
|
+
= f.save 'Save and Continue'
|
data/config/routes.rb
CHANGED
@@ -41,6 +41,7 @@ class CreateEffectiveEvents < ActiveRecord::Migration[6.0]
|
|
41
41
|
|
42
42
|
t.string :title
|
43
43
|
t.integer :capacity
|
44
|
+
t.boolean :waitlist, default: false
|
44
45
|
t.string :category
|
45
46
|
|
46
47
|
t.integer :regular_price
|
@@ -84,6 +85,11 @@ class CreateEffectiveEvents < ActiveRecord::Migration[6.0]
|
|
84
85
|
t.boolean :blank_registrant, default: false
|
85
86
|
t.boolean :member_registrant, default: false
|
86
87
|
|
88
|
+
t.boolean :waitlisted, default: false
|
89
|
+
t.boolean :promoted, default: false
|
90
|
+
|
91
|
+
t.datetime :registered_at
|
92
|
+
|
87
93
|
t.text :response1
|
88
94
|
t.text :response2
|
89
95
|
t.text :response3
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_events
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-06-
|
11
|
+
date: 2024-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -275,6 +275,7 @@ files:
|
|
275
275
|
- app/views/effective/event_registrations/_content.html.haml
|
276
276
|
- app/views/effective/event_registrations/_dashboard.html.haml
|
277
277
|
- app/views/effective/event_registrations/_event_registration.html.haml
|
278
|
+
- app/views/effective/event_registrations/_event_tickets.html.haml
|
278
279
|
- app/views/effective/event_registrations/_form_blank_registrants.html.haml
|
279
280
|
- app/views/effective/event_registrations/_layout.html.haml
|
280
281
|
- app/views/effective/event_registrations/_orders.html.haml
|
@@ -298,6 +299,7 @@ files:
|
|
298
299
|
- app/views/effective/events_mailer/event_registrant_purchased.liquid
|
299
300
|
- app/views/simple_calendar/_month_calendar.html.haml
|
300
301
|
- config/effective_events.rb
|
302
|
+
- config/locales/effective_events.en.yml
|
301
303
|
- config/locales/en.yml
|
302
304
|
- config/routes.rb
|
303
305
|
- db/migrate/101_create_effective_events.rb
|