effective_events 0.1.1 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/admin/event_products_controller.rb +8 -0
- data/app/controllers/admin/event_purchases_controller.rb +11 -0
- data/app/controllers/effective/event_registrations_controller.rb +2 -8
- data/app/datatables/admin/effective_event_products_datatable.rb +41 -0
- data/app/datatables/admin/effective_event_purchases_datatable.rb +41 -0
- data/app/datatables/admin/effective_event_registrations_datatable.rb +2 -1
- data/app/datatables/admin/effective_event_tickets_datatable.rb +1 -1
- data/app/datatables/effective_event_purchases_datatable.rb +38 -0
- data/app/datatables/effective_event_registrations_datatable.rb +1 -3
- data/app/helpers/effective_events_helper.rb +12 -1
- data/app/models/concerns/effective_events_event_registration.rb +21 -103
- data/app/models/effective/event.rb +8 -2
- data/app/models/effective/event_product.rb +53 -0
- data/app/models/effective/event_purchase.rb +71 -0
- data/app/models/effective/event_registrant.rb +1 -0
- data/app/models/effective/event_ticket.rb +1 -1
- data/app/views/admin/event_products/_form.html.haml +9 -0
- data/app/views/admin/event_purchases/_form.html.haml +14 -0
- data/app/views/admin/event_tickets/_form.html.haml +5 -1
- data/app/views/admin/events/_form.html.haml +21 -5
- data/app/views/effective/event_purchases/_fields.html.haml +10 -0
- data/app/views/effective/event_registrations/_purchases.html.haml +10 -0
- data/app/views/effective/event_registrations/purchases.html.haml +14 -0
- data/config/routes.rb +2 -0
- data/db/migrate/01_create_effective_events.rb.erb +35 -0
- data/lib/effective_events/version.rb +1 -1
- data/lib/generators/effective_events/install_generator.rb +1 -1
- metadata +14 -3
- data/app/views/effective/event_tickets/_fields.html.haml +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46897bd3260153bd17103b73716d32aca3b46d77335c9c8ac80b033ac881041b
|
4
|
+
data.tar.gz: 7da214c575b80246b79edc8c8c0467352e7629dea228a809db80a4c8fc53f14a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd8c3c426638f64c649408ea2da9ce57a5965c33c33aafde8255327b8c2eecf01ff0e8077b73d772575045e38e86f4648cdf79661f0b44d2d083e3ebab92a3e8
|
7
|
+
data.tar.gz: 4331ea43140b17dce1a0c0850688cf7b57627df10dbefde960d64fdf7cba63d63f3a285f79141a4c73a23f0941dc3f94632f5e1445201fbf0a97eac24c7c26f7
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Admin
|
2
|
+
class EventPurchasesController < ApplicationController
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
4
|
+
before_action { EffectiveResources.authorize!(self, :admin, :effective_events) }
|
5
|
+
|
6
|
+
include Effective::CrudController
|
7
|
+
|
8
|
+
submit :mark_paid, 'Save and Mark Paid'
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
@@ -6,7 +6,7 @@ module Effective
|
|
6
6
|
|
7
7
|
resource_scope -> {
|
8
8
|
event = Effective::Event.find(params[:event_id])
|
9
|
-
EffectiveEvents.EventRegistration.deep.where(owner:
|
9
|
+
EffectiveEvents.EventRegistration.deep.where(owner: current_user, event: event)
|
10
10
|
}
|
11
11
|
|
12
12
|
# Allow only 1 in-progress event registration at a time
|
@@ -37,16 +37,10 @@ module Effective
|
|
37
37
|
|
38
38
|
private
|
39
39
|
|
40
|
-
def current_owner
|
41
|
-
(current_user.class.respond_to?(:effective_memberships_owner?) ? current_user.effective_memberships_owners : current_user)
|
42
|
-
end
|
43
|
-
|
44
40
|
def permitted_params
|
45
41
|
model = (params.key?(:effective_event_registration) ? :effective_event_registration : :event_registration)
|
46
42
|
|
47
|
-
params.require(model).permit!.except(
|
48
|
-
:status, :status_steps, :wizard_steps, :submitted_at
|
49
|
-
)
|
43
|
+
params.require(model).permit!.except(:status, :status_steps, :wizard_steps, :submitted_at)
|
50
44
|
end
|
51
45
|
|
52
46
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Admin
|
2
|
+
class EffectiveEventProductsDatatable < Effective::Datatable
|
3
|
+
datatable do
|
4
|
+
reorder :position
|
5
|
+
|
6
|
+
col :updated_at, visible: false
|
7
|
+
col :created_at, visible: false
|
8
|
+
col :id, visible: false
|
9
|
+
|
10
|
+
col :event
|
11
|
+
|
12
|
+
col :title
|
13
|
+
col :price, as: :price
|
14
|
+
|
15
|
+
#col :capacity
|
16
|
+
col :purchased_event_purchases_count, label: 'Purchased'
|
17
|
+
|
18
|
+
col :purchased_event_purchases, label: 'Purchased by' do |product|
|
19
|
+
product.purchased_event_purchases.sort_by(&:to_s).map do |purchase|
|
20
|
+
content_tag(:div, purchase.owner.to_s, class: 'col-resource_item')
|
21
|
+
end.join.html_safe
|
22
|
+
end
|
23
|
+
|
24
|
+
actions_col
|
25
|
+
end
|
26
|
+
|
27
|
+
collection do
|
28
|
+
scope = Effective::EventProduct.deep.all
|
29
|
+
|
30
|
+
if attributes[:event_id]
|
31
|
+
scope = scope.where(event: event)
|
32
|
+
end
|
33
|
+
|
34
|
+
scope
|
35
|
+
end
|
36
|
+
|
37
|
+
def event
|
38
|
+
Effective::Event.find(attributes[:event_id])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Admin
|
2
|
+
class EffectiveEventPurchasesDatatable < Effective::Datatable
|
3
|
+
datatable do
|
4
|
+
col :updated_at, visible: false
|
5
|
+
col :created_at, visible: false
|
6
|
+
col :id, visible: false
|
7
|
+
|
8
|
+
col :event
|
9
|
+
|
10
|
+
col :event_registration, visible: false
|
11
|
+
|
12
|
+
if attributes[:event_id]
|
13
|
+
col :event_product, search: Effective::EventProduct.where(event: event).all
|
14
|
+
else
|
15
|
+
col :event_product, search: :string
|
16
|
+
end
|
17
|
+
|
18
|
+
col :purchased_order
|
19
|
+
col :owner
|
20
|
+
col :notes, label: 'Notes'
|
21
|
+
|
22
|
+
actions_col
|
23
|
+
end
|
24
|
+
|
25
|
+
collection do
|
26
|
+
scope = Effective::EventPurchase.deep.purchased
|
27
|
+
|
28
|
+
if attributes[:event_id].present?
|
29
|
+
scope = scope.where(event: event)
|
30
|
+
end
|
31
|
+
|
32
|
+
scope
|
33
|
+
end
|
34
|
+
|
35
|
+
def event
|
36
|
+
@event ||= if attributes[:event_id]
|
37
|
+
Effective::Event.find(attributes[:event_id])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -9,10 +9,11 @@ class Admin::EffectiveEventRegistrationsDatatable < Effective::Datatable
|
|
9
9
|
|
10
10
|
col :submitted_at, label: 'Submitted', visible: false, as: :date
|
11
11
|
|
12
|
-
col :event
|
12
|
+
col :event, search: :string
|
13
13
|
col :owner
|
14
14
|
|
15
15
|
col :event_registrants, search: :string
|
16
|
+
col :event_purchases, search: :string
|
16
17
|
col :orders, label: 'Order'
|
17
18
|
|
18
19
|
actions_col
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Used on the Event Registrations purchases step
|
2
|
+
|
3
|
+
class EffectiveEventPurchasesDatatable < Effective::Datatable
|
4
|
+
datatable do
|
5
|
+
|
6
|
+
col :event_product, search: :string
|
7
|
+
col :price, as: :price
|
8
|
+
col :notes
|
9
|
+
# no actions_col
|
10
|
+
end
|
11
|
+
|
12
|
+
collection do
|
13
|
+
scope = Effective::EventPurchase.deep.all
|
14
|
+
|
15
|
+
if event.present?
|
16
|
+
scope = scope.where(event: event)
|
17
|
+
end
|
18
|
+
|
19
|
+
if event_registration.present?
|
20
|
+
scope = scope.where(event_registration_id: event_registration)
|
21
|
+
end
|
22
|
+
|
23
|
+
scope
|
24
|
+
end
|
25
|
+
|
26
|
+
def event
|
27
|
+
@event ||= if attributes[:event_id]
|
28
|
+
Effective::Event.find(attributes[:event_id])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def event_registration
|
33
|
+
@event_registration ||= if attributes[:event_registration_id]
|
34
|
+
EffectiveEvents.EventRegistration.find_by_id(attributes[:event_registration_id])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -30,9 +30,7 @@ class EffectiveEventRegistrationsDatatable < Effective::Datatable
|
|
30
30
|
end
|
31
31
|
|
32
32
|
collection do
|
33
|
-
|
34
|
-
|
35
|
-
EffectiveEvents.EventRegistration.deep.where(owner: owner)
|
33
|
+
EffectiveEvents.EventRegistration.deep.where(owner: current_user)
|
36
34
|
end
|
37
35
|
|
38
36
|
end
|
@@ -5,12 +5,23 @@ module EffectiveEventsHelper
|
|
5
5
|
|
6
6
|
event.event_tickets.map do |ticket|
|
7
7
|
label = ticket.to_s
|
8
|
-
price = (ticket.price == 0 ? '$0' :
|
8
|
+
price = (ticket.price == 0 ? '$0' : price_to_currency(ticket.price))
|
9
9
|
|
10
10
|
["#{label} - #{price}", ticket.to_param]
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
+
def effective_events_event_products_collection(event)
|
15
|
+
raise('expected an Effective::Event') unless event.kind_of?(Effective::Event)
|
16
|
+
|
17
|
+
event.event_products.map do |product|
|
18
|
+
label = product.to_s
|
19
|
+
price = (product.price == 0 ? '$0' : price_to_currency(product.price))
|
20
|
+
|
21
|
+
["#{label} - #{price}", product.to_param]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
14
25
|
def edit_effective_event_registrations_wizard?
|
15
26
|
params[:controller] == 'effective/event_registrations' && defined?(resource) && resource.draft?
|
16
27
|
end
|
@@ -37,12 +37,15 @@ module EffectiveEventsEventRegistration
|
|
37
37
|
acts_as_wizard(
|
38
38
|
start: 'Start',
|
39
39
|
registrants: 'Registrants',
|
40
|
+
purchases: 'Purchases',
|
40
41
|
summary: 'Review',
|
41
42
|
billing: 'Billing Address',
|
42
43
|
checkout: 'Checkout',
|
43
44
|
submitted: 'Submitted'
|
44
45
|
)
|
45
46
|
|
47
|
+
acts_as_purchasable_wizard
|
48
|
+
|
46
49
|
log_changes(except: :wizard_steps) if respond_to?(:log_changes)
|
47
50
|
|
48
51
|
# Application Namespace
|
@@ -50,11 +53,14 @@ module EffectiveEventsEventRegistration
|
|
50
53
|
accepts_nested_attributes_for :owner
|
51
54
|
|
52
55
|
# Effective Namespace
|
53
|
-
belongs_to :event
|
56
|
+
belongs_to :event, class_name: 'Effective::Event'
|
54
57
|
|
55
|
-
has_many :event_registrants, -> { order(:id) }, inverse_of: :event_registration, dependent: :destroy
|
58
|
+
has_many :event_registrants, -> { order(:id) }, class_name: 'Effective::EventRegistrant', inverse_of: :event_registration, dependent: :destroy
|
56
59
|
accepts_nested_attributes_for :event_registrants, reject_if: :all_blank, allow_destroy: true
|
57
60
|
|
61
|
+
has_many :event_purchases, -> { order(:id) }, class_name: 'Effective::EventPurchase', inverse_of: :event_registration, dependent: :destroy
|
62
|
+
accepts_nested_attributes_for :event_purchases, reject_if: :all_blank, allow_destroy: true
|
63
|
+
|
58
64
|
has_many :orders, -> { order(:id) }, as: :parent, class_name: 'Effective::Order', dependent: :nullify
|
59
65
|
accepts_nested_attributes_for :orders
|
60
66
|
|
@@ -78,10 +84,7 @@ module EffectiveEventsEventRegistration
|
|
78
84
|
scope :in_progress, -> { where.not(status: [:submitted]) }
|
79
85
|
scope :done, -> { where(status: [:submitted]) }
|
80
86
|
|
81
|
-
scope :for, -> (user) {
|
82
|
-
owner = (user.respond_to?(:effective_memberships_owners) ? user.effective_memberships_owners : user)
|
83
|
-
where(owner: owner)
|
84
|
-
}
|
87
|
+
scope :for, -> (user) { where(owner: user) }
|
85
88
|
|
86
89
|
# All Steps validations
|
87
90
|
validates :owner, presence: true
|
@@ -92,17 +95,16 @@ module EffectiveEventsEventRegistration
|
|
92
95
|
self.errors.add(:event_registrants, "can't be blank") unless present_event_registrants.present?
|
93
96
|
end
|
94
97
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
self.errors.add(:base, "must have an email") unless owner.email.present?
|
98
|
+
def required_steps
|
99
|
+
return self.class.test_required_steps if Rails.env.test? && self.class.test_required_steps.present?
|
100
|
+
event&.event_products.present? ? wizard_step_keys : (wizard_step_keys - [:purchases])
|
99
101
|
end
|
100
102
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
after_submit_purchased!
|
103
|
+
# All Fees and Orders
|
104
|
+
def submit_fees
|
105
|
+
(event_registrants + event_purchases)
|
105
106
|
end
|
107
|
+
|
106
108
|
end
|
107
109
|
|
108
110
|
# Instance Methods
|
@@ -118,10 +120,6 @@ module EffectiveEventsEventRegistration
|
|
118
120
|
submitted?
|
119
121
|
end
|
120
122
|
|
121
|
-
def can_visit_step?(step)
|
122
|
-
can_revisit_completed_steps(step)
|
123
|
-
end
|
124
|
-
|
125
123
|
# Find or build
|
126
124
|
def event_registrant(first_name:, last_name:, email:)
|
127
125
|
registrant = event_registrants.find { |er| er.first_name == first_name && er.last_name == last_name && er.email == email }
|
@@ -132,96 +130,16 @@ module EffectiveEventsEventRegistration
|
|
132
130
|
def build_event_registrants
|
133
131
|
if event_registrants.blank?
|
134
132
|
raise('expected owner and event to be present') unless owner && event
|
135
|
-
event_registrants.build(
|
133
|
+
event_registrants.build(
|
134
|
+
first_name: owner.try(:first_name),
|
135
|
+
last_name: owner.try(:last_name),
|
136
|
+
email: owner.try(:email)
|
137
|
+
)
|
136
138
|
end
|
137
139
|
|
138
140
|
event_registrants
|
139
141
|
end
|
140
142
|
|
141
|
-
# All Fees and Orders
|
142
|
-
def submit_fees
|
143
|
-
event_registrants
|
144
|
-
end
|
145
|
-
|
146
|
-
def submit_order
|
147
|
-
orders.first
|
148
|
-
end
|
149
|
-
|
150
|
-
def find_or_build_submit_order
|
151
|
-
order = submit_order || orders.build(user: owner)
|
152
|
-
fees = submit_fees()
|
153
|
-
|
154
|
-
# Adds fees, but does not overwrite any existing price.
|
155
|
-
fees.each do |fee|
|
156
|
-
order.add(fee) unless order.purchasables.include?(fee)
|
157
|
-
end
|
158
|
-
|
159
|
-
order.purchasables.each do |purchasable|
|
160
|
-
order.remove(purchasable) unless fees.include?(purchasable)
|
161
|
-
end
|
162
|
-
|
163
|
-
# From Billing Step
|
164
|
-
order.billing_address = owner.billing_address if owner.billing_address.present?
|
165
|
-
|
166
|
-
# Important to add/remove anything
|
167
|
-
order.save
|
168
|
-
|
169
|
-
order
|
170
|
-
end
|
171
|
-
|
172
|
-
# Should be indempotent.
|
173
|
-
def build_submit_fees_and_order
|
174
|
-
return false if was_submitted?
|
175
|
-
|
176
|
-
fees = submit_fees()
|
177
|
-
raise('already has purchased submit fees') if fees.any?(&:purchased?)
|
178
|
-
|
179
|
-
order = find_or_build_submit_order()
|
180
|
-
raise('already has purchased submit order') if order.purchased?
|
181
|
-
|
182
|
-
true
|
183
|
-
end
|
184
|
-
|
185
|
-
# If they go back and change registrants. Update the order right away.
|
186
|
-
def registrants!
|
187
|
-
save!
|
188
|
-
build_submit_fees_and_order if submit_order.present?
|
189
|
-
true
|
190
|
-
end
|
191
|
-
|
192
|
-
# Owner clicks on the Billing step. Next step is Checkout
|
193
|
-
def billing!
|
194
|
-
ready!
|
195
|
-
end
|
196
|
-
|
197
|
-
# Ready to check out
|
198
|
-
def ready!
|
199
|
-
build_submit_fees_and_order
|
200
|
-
save!
|
201
|
-
end
|
202
|
-
|
203
|
-
# Called automatically via after_purchase hook above
|
204
|
-
def submit_purchased!
|
205
|
-
return false if was_submitted?
|
206
|
-
|
207
|
-
wizard_steps[:checkout] = Time.zone.now
|
208
|
-
submit!
|
209
|
-
end
|
210
|
-
|
211
|
-
# A hook to extend
|
212
|
-
def after_submit_purchased!
|
213
|
-
end
|
214
|
-
|
215
|
-
# Draft -> Submitted requirements
|
216
|
-
def submit!
|
217
|
-
raise('already submitted') if was_submitted?
|
218
|
-
raise('expected a purchased order') unless submit_order&.purchased?
|
219
|
-
|
220
|
-
wizard_steps[:checkout] ||= Time.zone.now
|
221
|
-
wizard_steps[:submitted] = Time.zone.now
|
222
|
-
submitted!
|
223
|
-
end
|
224
|
-
|
225
143
|
private
|
226
144
|
|
227
145
|
def present_event_registrants
|
@@ -2,11 +2,17 @@
|
|
2
2
|
|
3
3
|
module Effective
|
4
4
|
class Event < ActiveRecord::Base
|
5
|
+
has_many :event_tickets, -> { EventTicket.sorted }, inverse_of: :event
|
6
|
+
accepts_nested_attributes_for :event_tickets, allow_destroy: true
|
7
|
+
|
8
|
+
has_many :event_products, -> { EventProduct.sorted }, inverse_of: :event
|
9
|
+
accepts_nested_attributes_for :event_products, allow_destroy: true
|
10
|
+
|
5
11
|
has_many :event_registrants, -> { order(:event_ticket_id, :created_at) }, inverse_of: :event
|
6
12
|
accepts_nested_attributes_for :event_registrants, allow_destroy: true
|
7
13
|
|
8
|
-
has_many :
|
9
|
-
accepts_nested_attributes_for :
|
14
|
+
has_many :event_purchases, -> { order(:event_product_id, :created_at) }, inverse_of: :event
|
15
|
+
accepts_nested_attributes_for :event_purchases, allow_destroy: true
|
10
16
|
|
11
17
|
# rich_text_body - Used by the select step
|
12
18
|
has_many_rich_texts
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Effective
|
4
|
+
class EventProduct < ActiveRecord::Base
|
5
|
+
belongs_to :event
|
6
|
+
|
7
|
+
has_many :event_purchases
|
8
|
+
has_many :purchased_event_purchases, -> { EventPurchase.purchased }, class_name: 'Effective::EventPurchase'
|
9
|
+
|
10
|
+
log_changes(to: :event) if respond_to?(:log_changes)
|
11
|
+
|
12
|
+
has_rich_text :body
|
13
|
+
|
14
|
+
effective_resource do
|
15
|
+
title :string
|
16
|
+
capacity :integer
|
17
|
+
|
18
|
+
# Pricing
|
19
|
+
price :integer
|
20
|
+
|
21
|
+
qb_item_name :string
|
22
|
+
tax_exempt :boolean
|
23
|
+
|
24
|
+
position :integer
|
25
|
+
|
26
|
+
timestamps
|
27
|
+
end
|
28
|
+
|
29
|
+
scope :sorted, -> { order(:position) }
|
30
|
+
scope :deep, -> { with_rich_text_body.includes(:purchased_event_purchases) }
|
31
|
+
|
32
|
+
before_validation(if: -> { event.present? }) do
|
33
|
+
self.position ||= (event.event_products.map(&:position).compact.max || -1) + 1
|
34
|
+
end
|
35
|
+
|
36
|
+
validates :title, presence: true, uniqueness: { scope: [:event_id] }
|
37
|
+
validates :price, presence: true
|
38
|
+
|
39
|
+
def to_s
|
40
|
+
title.presence || 'New Event Product'
|
41
|
+
end
|
42
|
+
|
43
|
+
def capacity_available?
|
44
|
+
return true if capacity.blank?
|
45
|
+
capacity <= purchased_event_purchases.count
|
46
|
+
end
|
47
|
+
|
48
|
+
def purchased_event_purchases_count
|
49
|
+
purchased_event_purchases.count
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Just like each EventRegistration has EventTickets and EventRegistrants
|
4
|
+
# An Event Registration has EventProducts and EventPurchases
|
5
|
+
|
6
|
+
module Effective
|
7
|
+
class EventPurchase < ActiveRecord::Base
|
8
|
+
acts_as_purchasable
|
9
|
+
|
10
|
+
log_changes(to: :event) if respond_to?(:log_changes)
|
11
|
+
|
12
|
+
belongs_to :event, counter_cache: true
|
13
|
+
|
14
|
+
# Basically a category containing all the pricing and unique info about this product purchase
|
15
|
+
belongs_to :event_product
|
16
|
+
|
17
|
+
# Every event registrant is charged to a owner
|
18
|
+
belongs_to :owner, polymorphic: true
|
19
|
+
|
20
|
+
# This fee when checked out through the event registration
|
21
|
+
belongs_to :event_registration, polymorphic: true, optional: true
|
22
|
+
|
23
|
+
effective_resource do
|
24
|
+
notes :text
|
25
|
+
|
26
|
+
# Acts as Purchasable
|
27
|
+
price :integer
|
28
|
+
qb_item_name :string
|
29
|
+
tax_exempt :boolean
|
30
|
+
|
31
|
+
timestamps
|
32
|
+
end
|
33
|
+
|
34
|
+
scope :sorted, -> { order(:id) }
|
35
|
+
scope :deep, -> { all }
|
36
|
+
|
37
|
+
before_validation(if: -> { event_registration.present? }) do
|
38
|
+
self.event ||= event_registration.event
|
39
|
+
self.owner ||= event_registration.owner
|
40
|
+
end
|
41
|
+
|
42
|
+
before_validation(if: -> { event_product.present? }) do
|
43
|
+
self.price ||= event_product.price
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s
|
47
|
+
persisted? ? event_product.to_s : 'product'
|
48
|
+
end
|
49
|
+
|
50
|
+
def tax_exempt
|
51
|
+
event_product.tax_exempt
|
52
|
+
end
|
53
|
+
|
54
|
+
def qb_item_name
|
55
|
+
event_product.qb_item_name
|
56
|
+
end
|
57
|
+
|
58
|
+
# This is the Admin Save and Mark Paid action
|
59
|
+
def mark_paid!
|
60
|
+
raise('expected a blank event registration') if event_registration.present?
|
61
|
+
|
62
|
+
save!
|
63
|
+
|
64
|
+
order = Effective::Order.new(items: self, user: owner)
|
65
|
+
order.purchase!(skip_buyer_validations: true, email: false)
|
66
|
+
|
67
|
+
true
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -34,7 +34,7 @@ module Effective
|
|
34
34
|
self.position ||= (event.event_tickets.map(&:position).compact.max || -1) + 1
|
35
35
|
end
|
36
36
|
|
37
|
-
validates :title, presence: true
|
37
|
+
validates :title, presence: true, uniqueness: { scope: [:event_id] }
|
38
38
|
validates :regular_price, presence: true
|
39
39
|
validates :early_bird_price, presence: true, if: -> { event&.early_bird_end_at.present? }
|
40
40
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
= effective_form_with(model: [:admin, event_purchase], engine: true) do |f|
|
2
|
+
= f.hidden_field :event_id
|
3
|
+
|
4
|
+
- if f.object.new_record?
|
5
|
+
= f.select :owner, { 'Users' => current_user.class.all }, polymorphic: true
|
6
|
+
- else
|
7
|
+
= f.static_field :owner
|
8
|
+
|
9
|
+
= render 'effective/event_purchases/fields', f: f, event: event_purchase.event
|
10
|
+
|
11
|
+
- if f.object.new_record?
|
12
|
+
= f.submit 'Save and Mark Paid'
|
13
|
+
- else
|
14
|
+
= f.submit 'Save'
|
@@ -1,7 +1,11 @@
|
|
1
1
|
= effective_form_with(model: [:admin, event_ticket], engine: true) do |f|
|
2
2
|
= f.hidden_field :event_id
|
3
3
|
|
4
|
+
= f.text_field :title
|
5
|
+
= f.price_field :regular_price
|
6
|
+
= f.price_field :early_bird_price
|
7
|
+
= f.text_field :qb_item_name
|
8
|
+
= f.check_box :tax_exempt
|
4
9
|
/= f.number_field :capacity, hint: 'The number of online purchases will be loosely limited to capacity.'
|
5
|
-
= render 'effective/event_tickets/fields', f: f
|
6
10
|
|
7
11
|
= effective_submit(f)
|
@@ -3,20 +3,36 @@
|
|
3
3
|
= render 'admin/events/form_event', event: event
|
4
4
|
|
5
5
|
- if event.persisted?
|
6
|
-
= tab 'Registrants' do
|
7
|
-
- datatable = Admin::EffectiveEventRegistrantsDatatable.new(event_id: event.id)
|
8
|
-
= render_inline_datatable(datatable)
|
9
|
-
|
10
6
|
= tab 'Content' do
|
11
7
|
= render '/admin/events/form_content', event: event
|
12
8
|
|
13
9
|
= tab 'Tickets' do
|
14
10
|
%p An event must have tickets before registration can begin
|
15
11
|
|
12
|
+
%h2 Tickets
|
16
13
|
- datatable = Admin::EffectiveEventTicketsDatatable.new(event_id: event.id)
|
17
14
|
= render_inline_datatable(datatable)
|
18
15
|
|
19
|
-
= tab '
|
16
|
+
= tab 'Products' do
|
17
|
+
%h2 Products
|
18
|
+
- datatable = Admin::EffectiveEventProductsDatatable.new(event_id: event.id)
|
19
|
+
= render_inline_datatable(datatable)
|
20
|
+
|
21
|
+
= tab 'Registrations' do
|
22
|
+
%h2 Registrations
|
23
|
+
- datatable = Admin::EffectiveEventRegistrationsDatatable.new(event_id: event.id)
|
24
|
+
.mb-4= render_inline_datatable(datatable)
|
25
|
+
|
26
|
+
= tab 'Registrants' do
|
27
|
+
%h2 Registrants
|
28
|
+
- datatable = Admin::EffectiveEventRegistrantsDatatable.new(event_id: event.id)
|
29
|
+
.mb-4= render_inline_datatable(datatable)
|
30
|
+
|
31
|
+
%h2 Purchases
|
32
|
+
- datatable = Admin::EffectiveEventPurchasesDatatable.new(event_id: event.id)
|
33
|
+
= render_inline_datatable(datatable)
|
34
|
+
|
35
|
+
= tab 'Wizard' do
|
20
36
|
= render '/admin/events/form_event_registration_content', event: event
|
21
37
|
|
22
38
|
= tab 'Access' do
|
@@ -0,0 +1,10 @@
|
|
1
|
+
.card
|
2
|
+
.card-body
|
3
|
+
%h5.card-title Event Purchase
|
4
|
+
|
5
|
+
- if f.object.purchased?
|
6
|
+
= f.static_field :event_product, label: 'Purchased event product'
|
7
|
+
- else
|
8
|
+
= f.select :event_product_id, effective_events_event_products_collection(event)
|
9
|
+
|
10
|
+
= f.text_area :notes, label: 'Notes'
|
@@ -0,0 +1,10 @@
|
|
1
|
+
.card
|
2
|
+
.card-body
|
3
|
+
.row
|
4
|
+
.col-sm
|
5
|
+
%h5.card-title= event_registration.wizard_step_title(:purchases)
|
6
|
+
.col-sm-auto.text-right
|
7
|
+
= link_to('Edit', wizard_path(:purchases)) if edit_effective_event_registrations_wizard?
|
8
|
+
|
9
|
+
- datatable = EffectiveEventPurchasesDatatable.new(event_registration: event_registration)
|
10
|
+
.mb-4= render_simple_datatable(datatable)
|
@@ -0,0 +1,14 @@
|
|
1
|
+
= render 'layout' do
|
2
|
+
= render 'effective/event_registrations/content', resource: resource
|
3
|
+
|
4
|
+
.card
|
5
|
+
.card-body
|
6
|
+
%p Please add one or more products.
|
7
|
+
|
8
|
+
= effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
|
9
|
+
= f.hidden_field :id
|
10
|
+
|
11
|
+
= f.has_many :event_purchases do |fp|
|
12
|
+
= render('effective/event_purchases/fields', f: fp, event: f.object.event)
|
13
|
+
|
14
|
+
= f.save 'Save and Continue'
|
data/config/routes.rb
CHANGED
@@ -17,7 +17,9 @@ EffectiveEvents::Engine.routes.draw do
|
|
17
17
|
namespace :admin do
|
18
18
|
resources :events, except: [:show]
|
19
19
|
resources :event_tickets, except: [:show]
|
20
|
+
resources :event_products, except: [:show]
|
20
21
|
resources :event_registrants, except: [:show]
|
22
|
+
resources :event_purchases, except: [:show]
|
21
23
|
resources :event_registrations, only: [:index, :show]
|
22
24
|
end
|
23
25
|
|
@@ -14,6 +14,7 @@ class CreateEffectiveEvents < ActiveRecord::Migration[6.0]
|
|
14
14
|
t.datetime :early_bird_end_at
|
15
15
|
|
16
16
|
t.integer :event_registrants_count, default: 0
|
17
|
+
t.integer :event_purchases_count, default: 0
|
17
18
|
|
18
19
|
t.integer :roles_mask
|
19
20
|
t.boolean :authenticate_user, default: false
|
@@ -65,6 +66,40 @@ class CreateEffectiveEvents < ActiveRecord::Migration[6.0]
|
|
65
66
|
t.timestamps
|
66
67
|
end
|
67
68
|
|
69
|
+
create_table :event_products do |t|
|
70
|
+
t.integer :event_id
|
71
|
+
|
72
|
+
t.string :title
|
73
|
+
t.integer :capacity
|
74
|
+
|
75
|
+
t.integer :price
|
76
|
+
|
77
|
+
t.string :qb_item_name
|
78
|
+
t.boolean :tax_exempt, default: false
|
79
|
+
|
80
|
+
t.integer :position
|
81
|
+
|
82
|
+
t.timestamps
|
83
|
+
end
|
84
|
+
|
85
|
+
create_table :event_purchases do |t|
|
86
|
+
t.integer :event_id
|
87
|
+
t.integer :event_product_id
|
88
|
+
|
89
|
+
t.integer :owner_id
|
90
|
+
t.string :owner_type
|
91
|
+
|
92
|
+
t.integer :event_registration_id
|
93
|
+
t.string :event_registration_type
|
94
|
+
|
95
|
+
t.text :notes
|
96
|
+
|
97
|
+
t.integer :purchased_order_id
|
98
|
+
t.integer :price
|
99
|
+
|
100
|
+
t.timestamps
|
101
|
+
end
|
102
|
+
|
68
103
|
create_table :event_registrations do |t|
|
69
104
|
t.string :token
|
70
105
|
|
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.1.
|
4
|
+
version: 0.1.5
|
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: 2022-01-
|
11
|
+
date: 2022-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -179,25 +179,34 @@ files:
|
|
179
179
|
- app/assets/javascripts/effective_events/base.js
|
180
180
|
- app/assets/stylesheets/effective_events.scss
|
181
181
|
- app/assets/stylesheets/effective_events/base.scss
|
182
|
+
- app/controllers/admin/event_products_controller.rb
|
183
|
+
- app/controllers/admin/event_purchases_controller.rb
|
182
184
|
- app/controllers/admin/event_registrants_controller.rb
|
183
185
|
- app/controllers/admin/event_registrations_controller.rb
|
184
186
|
- app/controllers/admin/event_tickets_controller.rb
|
185
187
|
- app/controllers/admin/events_controller.rb
|
186
188
|
- app/controllers/effective/event_registrations_controller.rb
|
187
189
|
- app/controllers/effective/events_controller.rb
|
190
|
+
- app/datatables/admin/effective_event_products_datatable.rb
|
191
|
+
- app/datatables/admin/effective_event_purchases_datatable.rb
|
188
192
|
- app/datatables/admin/effective_event_registrants_datatable.rb
|
189
193
|
- app/datatables/admin/effective_event_registrations_datatable.rb
|
190
194
|
- app/datatables/admin/effective_event_tickets_datatable.rb
|
191
195
|
- app/datatables/admin/effective_events_datatable.rb
|
196
|
+
- app/datatables/effective_event_purchases_datatable.rb
|
192
197
|
- app/datatables/effective_event_registrants_datatable.rb
|
193
198
|
- app/datatables/effective_event_registrations_datatable.rb
|
194
199
|
- app/datatables/effective_events_datatable.rb
|
195
200
|
- app/helpers/effective_events_helper.rb
|
196
201
|
- app/models/concerns/effective_events_event_registration.rb
|
197
202
|
- app/models/effective/event.rb
|
203
|
+
- app/models/effective/event_product.rb
|
204
|
+
- app/models/effective/event_purchase.rb
|
198
205
|
- app/models/effective/event_registrant.rb
|
199
206
|
- app/models/effective/event_registration.rb
|
200
207
|
- app/models/effective/event_ticket.rb
|
208
|
+
- app/views/admin/event_products/_form.html.haml
|
209
|
+
- app/views/admin/event_purchases/_form.html.haml
|
201
210
|
- app/views/admin/event_registrants/_form.html.haml
|
202
211
|
- app/views/admin/event_tickets/_form.html.haml
|
203
212
|
- app/views/admin/events/_form.html.haml
|
@@ -205,21 +214,23 @@ files:
|
|
205
214
|
- app/views/admin/events/_form_content.html.haml
|
206
215
|
- app/views/admin/events/_form_event.html.haml
|
207
216
|
- app/views/admin/events/_form_event_registration_content.html.haml
|
217
|
+
- app/views/effective/event_purchases/_fields.html.haml
|
208
218
|
- app/views/effective/event_registrants/_fields.html.haml
|
209
219
|
- app/views/effective/event_registrations/_content.html.haml
|
210
220
|
- app/views/effective/event_registrations/_dashboard.html.haml
|
211
221
|
- app/views/effective/event_registrations/_event_registration.html.haml
|
212
222
|
- app/views/effective/event_registrations/_layout.html.haml
|
213
223
|
- app/views/effective/event_registrations/_orders.html.haml
|
224
|
+
- app/views/effective/event_registrations/_purchases.html.haml
|
214
225
|
- app/views/effective/event_registrations/_registrants.html.haml
|
215
226
|
- app/views/effective/event_registrations/_summary.html.haml
|
216
227
|
- app/views/effective/event_registrations/billing.html.haml
|
217
228
|
- app/views/effective/event_registrations/checkout.html.haml
|
229
|
+
- app/views/effective/event_registrations/purchases.html.haml
|
218
230
|
- app/views/effective/event_registrations/registrants.html.haml
|
219
231
|
- app/views/effective/event_registrations/start.html.haml
|
220
232
|
- app/views/effective/event_registrations/submitted.html.haml
|
221
233
|
- app/views/effective/event_registrations/summary.html.haml
|
222
|
-
- app/views/effective/event_tickets/_fields.html.haml
|
223
234
|
- app/views/effective/events/_dashboard.html.haml
|
224
235
|
- app/views/effective/events/_event.html.haml
|
225
236
|
- app/views/effective/events/_layout.html.haml
|