effective_events 0.10.2 → 0.11.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e0eded3c712c018bb91f9c90eebe522030fa7d02d5d73b9de4001bda7c5dbcf
4
- data.tar.gz: 3dc20c280ef92ebc93dad4cfe57df506e6a283bd4433a4792f07a236b3fb5ebc
3
+ metadata.gz: 908edb48306e3813893671ea9ba33cc3d1988258a47451edecfeee86197136a7
4
+ data.tar.gz: 7bb18df7c58fd2fa7e08b17710a1b5eefe22574690f1532243aab1e559cc44ec
5
5
  SHA512:
6
- metadata.gz: 43fcaa469c42cf91dcb5ac3f6c52509372a4d8983c91cac727d350f4c9a3a797f04d4cd1f4ee6793502a5eb868dbc1c660e51862b3a0ad299f1ad416a69c7220
7
- data.tar.gz: e7fe84b88841792c065bd307a80656ab4248b60306c2cfecaeb007ba09aa3b2bc782ee13512a91640e02c5b39156bb923bcd6683e889d51b36f99b2bd349bc67
6
+ metadata.gz: 5f9e45f483664485e43509d46bb0209a7567bd66b5bf27f425cfbe03ee6a3b0f171362db99d6faf7c2070074be3210239d59140f0989260c2b1fd18aa5b820ca
7
+ data.tar.gz: ac11a1ab1e15d1e58f5ab7e6db346906fcf6836caedbb6c45f94fbf57c177334b379da57ae8e91658b23d017fb8d62f790f740c82c0d2c2ab55662edcba6084d
@@ -13,26 +13,13 @@ module Effective
13
13
  EffectiveEvents.EventRegistration.deep.where(owner: current_user, event: event)
14
14
  }
15
15
 
16
- # Override ready_checkout to also check for any currently sold out tickets or addons
17
- # Prevents people from coming back and purchasing them
18
- def ready_checkout
19
- return unless step == :checkout
20
- return unless resource.class.try(:acts_as_purchasable_wizard?)
21
-
22
- if resource.sold_out_event_registrants.present? || resource.sold_out_event_addons.present?
23
- flash[:danger] = "Your selected event tickets are sold out. This event registration is no longer available."
24
- return redirect_to('/dashboard')
25
- end
26
-
27
- resource.ready!
28
- end
29
-
30
16
  # If the event is no longer registerable, do not let them continue
31
17
  def redirect_unless_registerable
32
18
  return if resource.blank?
19
+ return if resource.submitted?
33
20
  return if resource.event.blank?
34
21
  return if resource.event.registerable?
35
- return if resource.submitted?
22
+ return if resource.submit_order&.deferred?
36
23
 
37
24
  flash[:danger] = "Your selected event is no longer available for registration. This event registration is no longer available."
38
25
  return redirect_to('/dashboard')
@@ -23,8 +23,8 @@ module Admin
23
23
  col :event_product, search: :string
24
24
  end
25
25
 
26
- col :purchased_order
27
- col :owner
26
+ col :purchased_order, visible: false
27
+ col :owner, visible: false
28
28
 
29
29
  col :first_name
30
30
  col :last_name
@@ -24,13 +24,21 @@ module Admin
24
24
  end
25
25
  end
26
26
 
27
- col :purchased_event_addons_count, label: 'Purchased'
27
+ col :registered_event_addons_count, label: 'Registered'
28
+ col :purchased_event_addons_count, label: 'Purchased', visible: false
29
+
28
30
  col :capacity, visible: false
29
31
  col :capacity_available, visible: false
30
32
 
31
- col :purchased_event_addons, label: 'Name' do |product|
32
- product.purchased_event_addons.reject(&:archived?).sort_by(&:to_s).map do |purchase|
33
- content_tag(:div, purchase.owner.to_s, class: 'col-resource_item')
33
+ col :registered_event_addons, label: 'Registered Names' do |product|
34
+ product.registered_event_addons.reject(&:archived?).sort_by(&:to_s).map do |addon|
35
+ content_tag(:div, addon.owner.to_s, class: 'col-resource_item')
36
+ end.join.html_safe
37
+ end
38
+
39
+ col :purchased_event_addons, label: 'Purchased Names', visible: false do |product|
40
+ product.purchased_event_addons.reject(&:archived?).sort_by(&:to_s).map do |addon|
41
+ content_tag(:div, addon.owner.to_s, class: 'col-resource_item')
34
42
  end.join.html_safe
35
43
  end
36
44
 
@@ -25,7 +25,11 @@ module Admin
25
25
  end
26
26
  end
27
27
 
28
- col :purchased_event_registrants_count, label: 'Registered' do |event|
28
+ col :registered_event_registrants_count, label: 'Registered' do |event|
29
+ event.event_registrants.registered.unarchived.count
30
+ end
31
+
32
+ col :purchased_event_registrants_count, label: 'Purchased', visible: false do |event|
29
33
  event.event_registrants.purchased.unarchived.count
30
34
  end
31
35
 
@@ -20,7 +20,7 @@ module EffectiveEventsHelper
20
20
  remaining = (ticket.capacity.present? ? "#{ticket.capacity_available} remaining" : nil)
21
21
 
22
22
  label = [title, price, remaining].compact.join(' - ')
23
- disabled = { disabled: :disabled } unless (authorized || ticket.available?)
23
+ disabled = { disabled: :disabled } unless (authorized || event.event_ticket_available?(ticket, quantity: 1))
24
24
 
25
25
  [label, ticket.to_param, disabled].compact
26
26
  end
@@ -39,7 +39,7 @@ module EffectiveEventsHelper
39
39
  remaining = (product.capacity.present? ? "#{product.capacity_available} remaining" : nil)
40
40
 
41
41
  label = [title, price, remaining].compact.join(' - ')
42
- disabled = { disabled: :disabled } unless (authorized || product.available?)
42
+ disabled = { disabled: :disabled } unless (authorized || event.event_product_available?(product, quantity: 1))
43
43
 
44
44
  [label, product.to_param, disabled].compact
45
45
  end
@@ -105,16 +105,17 @@ module EffectiveEventsEventRegistration
105
105
  self.errors.add(:event_registrants, "can't be blank") unless present_event_registrants.present?
106
106
  end
107
107
 
108
- # Validate all items are available
109
- validate(unless: -> { current_step == :checkout || done? }) do
110
- sold_out_event_registrants.each do |item|
111
- errors.add(:base, "The #{item.event_ticket} ticket is sold out and no longer available for purchase")
112
- item.errors.add(:event_ticket_id, "#{item.event_ticket} is unavailable for purchase")
108
+ # Validate all tickets are available for registration
109
+ validate(if: -> { current_step == :tickets }) do
110
+ unavailable_event_tickets.each do |event_ticket|
111
+ errors.add(:base, "The requested number of #{event_ticket} tickets are not available")
113
112
  end
113
+ end
114
114
 
115
- sold_out_event_addons.each do |item|
116
- errors.add(:base, "The #{item.event_product} product is sold out and no longer available for purchase")
117
- item.errors.add(:event_product_id, "#{item.event_product} is unavailable for purchase")
115
+ # Validate all products are available for registration
116
+ validate(if: -> { current_step == :addons }) do
117
+ unavailable_event_products.each do |event_product|
118
+ errors.add(:base, "The requested number of #{event_product} add-ons are not available")
118
119
  end
119
120
  end
120
121
 
@@ -126,27 +127,24 @@ module EffectiveEventsEventRegistration
126
127
  # All Fees and Orders
127
128
  def submit_fees
128
129
  if owner.respond_to?(:outstanding_coupon_fees) # effective_memberships_owner
129
- # Order item price reduction handled by reduce_order_item_coupon_fee_price in acts_as_purchasable_wizard
130
- Array(owner.outstanding_coupon_fees).each { |fee| fees << fee unless fees.include?(fee) }
131
130
  (event_registrants + event_addons + fees)
132
131
  else
133
132
  (event_registrants + event_addons)
134
133
  end
135
134
  end
136
135
 
137
- def after_submit_purchased!
138
- notifications = event.event_notifications.select(&:registrant_purchased?)
139
- notifications.each { |notification| notification.notify!(event_registrants: event_registrants) }
140
- end
136
+ def apply_outstanding_coupon_fees
137
+ return unless owner.respond_to?(:outstanding_coupon_fees)
141
138
 
142
- def sold_out_event_registrants
143
- event_registrants.reject { |er| er.purchased? || er.event_ticket&.available? }
144
- end
139
+ Array(owner.outstanding_coupon_fees).each { |fee| fees << fee unless fees.include?(fee) }
145
140
 
146
- def sold_out_event_addons
147
- event_addons.reject { |ep| ep.purchased? || ep.event_product&.available? }
141
+ fees.select { |fee| fee.try(:coupon_fee?) }
148
142
  end
149
143
 
144
+ def after_submit_purchased!
145
+ notifications = event.event_notifications.select(&:registrant_purchased?)
146
+ notifications.each { |notification| notification.notify!(event_registrants: event_registrants) }
147
+ end
150
148
  end
151
149
 
152
150
  # Instance Methods
@@ -206,10 +204,34 @@ module EffectiveEventsEventRegistration
206
204
  event_addons
207
205
  end
208
206
 
207
+ def unavailable_event_tickets
208
+ unavailable = []
209
+
210
+ present_event_registrants.map(&:event_ticket).group_by { |t| t }.each do |event_ticket, event_tickets|
211
+ unavailable << event_ticket unless event.event_ticket_available?(event_ticket, quantity: event_tickets.length)
212
+ end
213
+
214
+ unavailable
215
+ end
216
+
217
+ def unavailable_event_products
218
+ unavailable = []
219
+
220
+ present_event_addons.map(&:event_product).group_by { |p| p }.each do |event_product, event_products|
221
+ unavailable << event_product unless event.event_product_available?(event_product, quantity: event_products.length)
222
+ end
223
+
224
+ unavailable
225
+ end
226
+
209
227
  private
210
228
 
211
229
  def present_event_registrants
212
- event_registrants.reject(&:marked_for_destruction?)
230
+ event_registrants.reject(&:marked_for_destruction?).reject(&:archived?)
231
+ end
232
+
233
+ def present_event_addons
234
+ event_addons.reject(&:marked_for_destruction?).reject(&:archived?)
213
235
  end
214
236
 
215
237
  end
@@ -24,6 +24,10 @@ module Effective
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
+ # 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
30
+
27
31
  # rich_text_body - Used by the select step
28
32
  has_many_rich_texts
29
33
 
@@ -186,7 +190,8 @@ module Effective
186
190
  end
187
191
 
188
192
  def sold_out?
189
- false
193
+ return false unless event_tickets.present?
194
+ event_tickets.none? { |event_ticket| event_ticket_available?(event_ticket, quantity: 1) }
190
195
  end
191
196
 
192
197
  def early_bird?
@@ -229,5 +234,35 @@ module Effective
229
234
  start_at
230
235
  end
231
236
 
237
+ # Can I register/purchase this many new event tickets?
238
+ def event_ticket_available?(event_ticket, quantity:)
239
+ raise('expected an EventTicket') unless event_ticket.kind_of?(Effective::EventTicket)
240
+ raise('expected quantity to be greater than 0') unless quantity.to_i > 0
241
+
242
+ return false if event_ticket.archived?
243
+ return true if event_ticket.capacity.blank? # No capacity enforced for this ticket
244
+
245
+ # Total number already sold
246
+ registered = registered_event_registrants.count { |r| r.event_ticket_id == event_ticket.id }
247
+
248
+ # If there's capacity for this many more
249
+ (registered + quantity) <= event_ticket.capacity
250
+ end
251
+
252
+ # Can I register/purchase this many new event products?
253
+ def event_product_available?(event_product, quantity:)
254
+ raise('expected an EventProduct') unless event_product.kind_of?(Effective::EventProduct)
255
+ raise('expected quantity to be greater than 0') unless quantity.to_i > 0
256
+
257
+ return false if event_product.archived?
258
+ return true if event_product.capacity.blank? # No capacity enforced for this product
259
+
260
+ # Total number already sold
261
+ registered = registered_event_addons.count { |r| r.event_product_id == event_product.id }
262
+
263
+ # If there's capacity for this many more
264
+ (registered + quantity) <= event_product.capacity
265
+ end
266
+
232
267
  end
233
268
  end
@@ -42,6 +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.unarchived }
45
46
 
46
47
  before_validation(if: -> { event_registration.present? }) do
47
48
  self.event ||= event_registration.event
@@ -9,7 +9,8 @@ module Effective
9
9
  belongs_to :event
10
10
 
11
11
  has_many :event_addons
12
- has_many :purchased_event_addons, -> { EventAddon.purchased }, class_name: 'Effective::EventAddon'
12
+ has_many :purchased_event_addons, -> { EventAddon.purchased.unarchived }, class_name: 'Effective::EventAddon'
13
+ has_many :registered_event_addons, -> { EventAddon.registered.unarchived }, class_name: 'Effective::EventAddon'
13
14
 
14
15
  log_changes(to: :event) if respond_to?(:log_changes)
15
16
 
@@ -45,23 +46,17 @@ module Effective
45
46
  title.presence || 'New Event Product'
46
47
  end
47
48
 
48
- # Available for purchase
49
- def available?
50
- return false if archived?
51
- capacity_available?
52
- end
53
-
54
- def capacity_available?
55
- capacity.blank? || (capacity_available > 0)
56
- end
57
-
58
49
  def capacity_available
59
50
  return nil if capacity.blank?
60
- [(capacity - purchased_event_addons_count), 0].max
51
+ [(capacity - registered_event_addons_count), 0].max
52
+ end
53
+
54
+ def registered_event_addons_count
55
+ registered_event_addons.length
61
56
  end
62
57
 
63
58
  def purchased_event_addons_count
64
- purchased_event_addons.reject(&:archived?).length
59
+ purchased_event_addons.length
65
60
  end
66
61
 
67
62
  end
@@ -41,6 +41,7 @@ module Effective
41
41
 
42
42
  scope :sorted, -> { order(:last_name) }
43
43
  scope :deep, -> { includes(:event, :event_ticket) }
44
+ scope :registered, -> { purchased_or_deferred.unarchived }
44
45
 
45
46
  validates :first_name, presence: true
46
47
  validates :last_name, presence: true
@@ -9,7 +9,8 @@ module Effective
9
9
  belongs_to :event
10
10
 
11
11
  has_many :event_registrants
12
- has_many :purchased_event_registrants, -> { EventRegistrant.purchased }, class_name: 'Effective::EventRegistrant'
12
+ 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'
13
14
 
14
15
  log_changes(to: :event) if respond_to?(:log_changes)
15
16
 
@@ -51,23 +52,17 @@ module Effective
51
52
  event.early_bird? ? early_bird_price : regular_price
52
53
  end
53
54
 
54
- # Available for purchase
55
- def available?
56
- return false if archived?
57
- capacity_available?
58
- end
59
-
60
- def capacity_available?
61
- capacity.blank? || (capacity_available > 0)
62
- end
63
-
64
55
  def capacity_available
65
56
  return nil if capacity.blank?
66
- [(capacity - purchased_event_registrants_count), 0].max
57
+ [(capacity - registered_event_registrants_count), 0].max
58
+ end
59
+
60
+ def registered_event_registrants_count
61
+ registered_event_registrants.length
67
62
  end
68
63
 
69
64
  def purchased_event_registrants_count
70
- purchased_event_registrants.reject(&:archived?).length
65
+ purchased_event_registrants.length
71
66
  end
72
67
 
73
68
  end
@@ -1,6 +1,18 @@
1
1
  = render 'layout' do
2
2
  = render 'effective/event_registrations/content', resource: resource
3
3
 
4
- .card
5
- .card-body
6
- = render_checkout_step2(resource.submit_order, purchased_url: wizard_path(:submitted), deferred_url: wizard_path(:checkout), declined_url: wizard_path(:checkout))
4
+ - if resource.submit_order.deferred?
5
+ .card
6
+ .card-body
7
+ = render_checkout_step2(resource.submit_order, purchased_url: wizard_path(:submitted), deferred_url: wizard_path(:checkout), declined_url: wizard_path(:checkout))
8
+ - elsif resource.event.registerable? == false
9
+ .alert.alert-danger Your selected event is no longer available for registration.
10
+ - elsif resource.unavailable_event_tickets.present?
11
+ .alert.alert-danger Your selected number of event tickets are no longer available.
12
+ - elsif resource.unavailable_event_products.present?
13
+ .alert.alert-danger Your selected number of event add-ons are no longer available.
14
+ - else
15
+ .card
16
+ .card-body
17
+ = render_checkout_step2(resource.submit_order, purchased_url: wizard_path(:submitted), deferred_url: wizard_path(:checkout), declined_url: wizard_path(:checkout))
18
+
@@ -1,3 +1,3 @@
1
1
  module EffectiveEvents
2
- VERSION = '0.10.2'.freeze
2
+ VERSION = '0.11.1'.freeze
3
3
  end
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.10.2
4
+ version: 0.11.1
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: 2023-12-11 00:00:00.000000000 Z
11
+ date: 2024-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -178,6 +178,20 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: effective_roles
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
181
195
  - !ruby/object:Gem::Dependency
182
196
  name: psych
183
197
  requirement: !ruby/object:Gem::Requirement