effective_memberships 0.3.13 → 0.4.1
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/organizations_controller.rb +19 -0
- data/app/controllers/admin/representatives_controller.rb +19 -0
- data/app/controllers/effective/applicants_controller.rb +2 -3
- data/app/controllers/effective/fee_payments_controller.rb +1 -2
- data/app/controllers/effective/organizations_controller.rb +16 -0
- data/app/controllers/effective/representatives_controller.rb +19 -0
- data/app/datatables/admin/effective_applicants_datatable.rb +10 -5
- data/app/datatables/admin/effective_categories_datatable.rb +7 -0
- data/app/datatables/admin/effective_fee_payments_datatable.rb +11 -6
- data/app/datatables/admin/effective_organizations_datatable.rb +31 -0
- data/app/datatables/admin/effective_representatives_datatable.rb +28 -0
- data/app/datatables/effective_applicants_datatable.rb +1 -1
- data/app/datatables/effective_fee_payments_datatable.rb +5 -4
- data/app/datatables/effective_organizations_datatable.rb +18 -0
- data/app/datatables/effective_representatives_datatable.rb +40 -0
- data/app/helpers/effective_memberships_helper.rb +25 -0
- data/app/mailers/effective/memberships_mailer.rb +34 -15
- data/app/models/concerns/effective_memberships_applicant.rb +63 -30
- data/app/models/concerns/effective_memberships_category.rb +32 -5
- data/app/models/concerns/effective_memberships_fee_payment.rb +44 -45
- data/app/models/concerns/effective_memberships_organization.rb +94 -0
- data/app/models/concerns/effective_memberships_owner.rb +0 -55
- data/app/models/concerns/effective_memberships_registrar.rb +5 -3
- data/app/models/concerns/effective_memberships_user.rb +70 -0
- data/app/models/effective/fee.rb +1 -1
- data/app/models/effective/organization.rb +8 -0
- data/app/models/effective/registrar_action.rb +16 -1
- data/app/models/effective/representative.rb +56 -0
- data/app/views/admin/categories/_form_applicant_eligibility.html.haml +1 -1
- data/app/views/admin/categories/_form_applicant_steps.html.haml +29 -24
- data/app/views/admin/categories/_form_category.html.haml +3 -0
- data/app/views/admin/categories/_form_renewals.html.haml +0 -2
- data/app/views/admin/organizations/_fields.html.haml +6 -0
- data/app/views/admin/organizations/_form.html.haml +31 -0
- data/app/views/admin/organizations/_form_organization.html.haml +23 -0
- data/app/views/admin/registrar_actions/_form_fees_paid.html.haml +16 -0
- data/app/views/admin/representatives/_form.html.haml +38 -0
- data/app/views/{effective/applicants/_demographics_fields.html.haml → admin/representatives/_user_fields.html.haml} +2 -6
- data/app/views/effective/applicants/_dashboard.html.haml +24 -5
- data/app/views/effective/applicants/_demographics.html.haml +1 -1
- data/app/views/effective/applicants/_missing_info.html.haml +7 -3
- data/app/views/effective/applicants/_organization.html.haml +9 -0
- data/app/views/effective/applicants/_select_organization.html.haml +21 -0
- data/app/views/effective/applicants/_summary.html.haml +17 -9
- data/app/views/effective/applicants/billing.html.haml +2 -2
- data/app/views/effective/applicants/demographics.html.haml +7 -6
- data/app/views/effective/applicants/education.html.haml +2 -2
- data/app/views/effective/applicants/organization.html.haml +19 -0
- data/app/views/effective/applicants/references.html.haml +1 -1
- data/app/views/effective/applicants/select.html.haml +11 -1
- data/app/views/effective/applicants/stamp.html.haml +2 -2
- data/app/views/effective/applicants/start.html.haml +17 -11
- data/app/views/effective/applicants/submitted.html.haml +5 -5
- data/app/views/effective/applicants/summary.html.haml +1 -1
- data/app/views/effective/fee_payments/_demographics.html.haml +1 -1
- data/app/views/effective/fee_payments/_organization.html.haml +9 -0
- data/app/views/effective/fee_payments/_summary.html.haml +39 -1
- data/app/views/effective/fee_payments/billing.html.haml +2 -2
- data/app/views/effective/fee_payments/demographics.html.haml +2 -2
- data/app/views/effective/fee_payments/organization.html.haml +18 -0
- data/app/views/effective/fee_payments/start.html.haml +20 -17
- data/app/views/effective/fee_payments/submitted.html.haml +10 -3
- data/app/views/effective/fees/_dashboard.html.haml +20 -8
- data/app/views/effective/memberships/_dashboard.html.haml +16 -5
- data/app/views/effective/organizations/_dashboard.html.haml +10 -0
- data/app/views/effective/organizations/_form.html.haml +8 -0
- data/app/views/effective/organizations/_form_organization.html.haml +11 -0
- data/app/views/effective/representatives/_form.html.haml +33 -0
- data/app/views/effective/{fee_payments/_demographics_fields.html.haml → representatives/_user_fields.html.haml} +2 -6
- data/app/views/organizations/_demographics.html.haml +45 -0
- data/app/views/organizations/_fields_demographics.html.haml +29 -0
- data/app/views/users/_demographics.html.haml +50 -0
- data/app/views/users/_fields_demographics.html.haml +29 -0
- data/config/effective_memberships.rb +4 -0
- data/config/routes.rb +9 -0
- data/db/migrate/01_create_effective_memberships.rb.erb +57 -10
- data/db/seeds.rb +18 -0
- data/lib/effective_memberships/engine.rb +3 -0
- data/lib/effective_memberships/version.rb +1 -1
- data/lib/effective_memberships.rb +7 -3
- metadata +33 -20
- data/app/views/effective/applicants/_demographics_owner.html.haml +0 -20
- data/app/views/effective/fee_payments/_demographics_owner.html.haml +0 -20
@@ -44,7 +44,8 @@ module EffectiveMembershipsApplicant
|
|
44
44
|
acts_as_wizard(
|
45
45
|
start: 'Start',
|
46
46
|
select: 'Select Application Type',
|
47
|
-
demographics: 'Demographics',
|
47
|
+
demographics: 'Demographics', # Individual only. Users fields.
|
48
|
+
organization: 'Organization', # Organization only. Organization fields.
|
48
49
|
education: 'Education',
|
49
50
|
course_amounts: 'Courses',
|
50
51
|
experience: 'Work Experience',
|
@@ -73,8 +74,11 @@ module EffectiveMembershipsApplicant
|
|
73
74
|
attr_accessor :approved_membership_date
|
74
75
|
|
75
76
|
# Application Namespace
|
76
|
-
belongs_to :
|
77
|
-
accepts_nested_attributes_for :
|
77
|
+
belongs_to :user, polymorphic: true
|
78
|
+
accepts_nested_attributes_for :user
|
79
|
+
|
80
|
+
belongs_to :organization, polymorphic: true, optional: true
|
81
|
+
accepts_nested_attributes_for :organization
|
78
82
|
|
79
83
|
belongs_to :category, polymorphic: true, optional: true
|
80
84
|
belongs_to :from_category, polymorphic: true, optional: true
|
@@ -142,7 +146,7 @@ module EffectiveMembershipsApplicant
|
|
142
146
|
timestamps
|
143
147
|
end
|
144
148
|
|
145
|
-
scope :deep, -> { includes(:
|
149
|
+
scope :deep, -> { includes(:user, :organization, :category, :from_category, :orders) }
|
146
150
|
scope :sorted, -> { order(:id) }
|
147
151
|
|
148
152
|
scope :in_progress, -> { where.not(status: [:approved, :declined]) }
|
@@ -150,14 +154,15 @@ module EffectiveMembershipsApplicant
|
|
150
154
|
|
151
155
|
scope :not_draft, -> { where.not(status: :draft) }
|
152
156
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
end
|
157
|
+
scope :for, -> (user) {
|
158
|
+
raise('expected a effective memberships user') unless user.class.try(:effective_memberships_user?)
|
159
|
+
where(user: user).or(where(organization: user.organizations))
|
160
|
+
}
|
158
161
|
|
159
|
-
|
160
|
-
|
162
|
+
# Set Apply to Join or Reclassification
|
163
|
+
before_validation(if: -> { (new_record? || current_step == :select) && owner.present? }) do
|
164
|
+
self.applicant_type = (owner.membership.blank? ? 'Apply to Join' : 'Apply to Reclassify')
|
165
|
+
self.from_category = owner.membership&.category
|
161
166
|
end
|
162
167
|
|
163
168
|
before_validation(if: -> { current_step == :experience }) do
|
@@ -165,18 +170,16 @@ module EffectiveMembershipsApplicant
|
|
165
170
|
end
|
166
171
|
|
167
172
|
# All Steps validations
|
168
|
-
validates :
|
173
|
+
validates :user, presence: true
|
169
174
|
validates :from_category, presence: true, if: -> { reclassification? }
|
170
175
|
|
171
176
|
validate(if: -> { reclassification? }) do
|
172
177
|
errors.add(:category_id, "can't reclassify to existing category") if category_id == from_category_id
|
173
178
|
end
|
174
179
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
errors.add(:base, 'may not have outstanding fees') if owner.outstanding_fee_payment_fees.present?
|
179
|
-
end
|
180
|
+
validate(if: -> { category.present? }) do
|
181
|
+
self.errors.add(:organization_id, "can't be blank when organization category") if category.organization? && organization.blank?
|
182
|
+
self.errors.add(:organization_id, "must be blank when individual category") if category.individual? && organization.present?
|
180
183
|
end
|
181
184
|
|
182
185
|
# Select Step
|
@@ -185,6 +188,10 @@ module EffectiveMembershipsApplicant
|
|
185
188
|
validates :category, presence: true
|
186
189
|
end
|
187
190
|
|
191
|
+
validate(if: -> { current_step == :select && owner.present? }) do
|
192
|
+
self.errors.add(:base, 'may not have outstanding fees') if owner.outstanding_fee_payment_fees.present?
|
193
|
+
end
|
194
|
+
|
188
195
|
# Applicant Educations Step
|
189
196
|
with_options(if: -> { current_step == :education }) do
|
190
197
|
validate do
|
@@ -291,6 +298,14 @@ module EffectiveMembershipsApplicant
|
|
291
298
|
|
292
299
|
# Special logic for stamp step
|
293
300
|
applicant_steps.delete(:stamp) unless apply_to_join?
|
301
|
+
applicant_steps.delete(:organization) unless category&.organization?
|
302
|
+
|
303
|
+
# change_wizard_steps is defined in effective_resources acts_as_wizard
|
304
|
+
applicant_steps = change_wizard_steps(applicant_steps)
|
305
|
+
|
306
|
+
unless applicant_steps.kind_of?(Array) && applicant_steps.all? { |step| step.kind_of?(Symbol) }
|
307
|
+
raise('expected change_wizard_steps to return an Array of steps with no nils')
|
308
|
+
end
|
294
309
|
|
295
310
|
wizard_steps.select do |step|
|
296
311
|
required_steps.include?(step) || category.blank? || applicant_steps.include?(step)
|
@@ -370,6 +385,18 @@ module EffectiveMembershipsApplicant
|
|
370
385
|
end
|
371
386
|
end
|
372
387
|
|
388
|
+
def owner
|
389
|
+
organization || user
|
390
|
+
end
|
391
|
+
|
392
|
+
def owner_symbol
|
393
|
+
organization? ? :organization : :user
|
394
|
+
end
|
395
|
+
|
396
|
+
def build_organization(params = {})
|
397
|
+
self.organization = EffectiveMemberships.Organization.new(params)
|
398
|
+
end
|
399
|
+
|
373
400
|
def apply_to_join?
|
374
401
|
applicant_type == 'Apply to Join'
|
375
402
|
end
|
@@ -378,8 +405,12 @@ module EffectiveMembershipsApplicant
|
|
378
405
|
applicant_type == 'Apply to Reclassify'
|
379
406
|
end
|
380
407
|
|
381
|
-
def
|
382
|
-
|
408
|
+
def individual?
|
409
|
+
!(owner.kind_of?(EffectiveMemberships.Organization) && category&.organization?)
|
410
|
+
end
|
411
|
+
|
412
|
+
def organization?
|
413
|
+
owner.kind_of?(EffectiveMemberships.Organization) && category&.organization?
|
383
414
|
end
|
384
415
|
|
385
416
|
def in_progress?
|
@@ -399,9 +430,11 @@ module EffectiveMembershipsApplicant
|
|
399
430
|
when 'draft'
|
400
431
|
"Applicant has not yet completed the #{category} wizard steps or paid to submit this application. This application will transition to 'submitted' after payment has been collected."
|
401
432
|
when 'submitted'
|
402
|
-
summary = "Application has been purchased and submitted.
|
433
|
+
summary = "Application has been purchased and submitted."
|
434
|
+
tasks = "The following tasks remain before it can be completed:"
|
435
|
+
approval = "Waiting on approval."
|
403
436
|
items = completed_requirements.map { |item, done| "<li>#{item}: #{done ? 'Complete' : 'Incomplete'}</li>" }.join
|
404
|
-
"<p>#{summary}</p><ul>#{items}</ul>"
|
437
|
+
completed_requirements.present? ? "<p>#{summary} #{tasks}</p><ul>#{items}</ul>" : "#{summary} #{approval}"
|
405
438
|
when 'completed'
|
406
439
|
if applicant_reviews_required?
|
407
440
|
"All required materials have been provided. This application will transition to 'reviewed' after all reviewers have voted."
|
@@ -425,11 +458,11 @@ module EffectiveMembershipsApplicant
|
|
425
458
|
def can_apply_categories_collection
|
426
459
|
categories = EffectiveMemberships.Category.sorted.can_apply
|
427
460
|
|
428
|
-
if
|
461
|
+
if user.blank? || !user.is?(:member)
|
429
462
|
return categories.where(can_apply_new: true)
|
430
463
|
end
|
431
464
|
|
432
|
-
category_ids =
|
465
|
+
category_ids = user.memberships.map(&:category_ids).flatten
|
433
466
|
|
434
467
|
categories.select do |cat|
|
435
468
|
cat.can_apply_existing? ||
|
@@ -503,10 +536,6 @@ module EffectiveMembershipsApplicant
|
|
503
536
|
)
|
504
537
|
end
|
505
538
|
|
506
|
-
# The submit! method used to be here
|
507
|
-
# But it needs to be inside the included do block
|
508
|
-
# So see above. Sorry.
|
509
|
-
|
510
539
|
def applicant_references_required?
|
511
540
|
min_applicant_references > 0
|
512
541
|
end
|
@@ -514,9 +543,13 @@ module EffectiveMembershipsApplicant
|
|
514
543
|
# When an application is submitted, these must be done to go to completed.
|
515
544
|
# An Admin can override this and just set them to completed.
|
516
545
|
def completed_requirements
|
517
|
-
|
518
|
-
|
519
|
-
|
546
|
+
if category&.applicant_wizard_steps&.include?(:references) || applicant_references_required?
|
547
|
+
{
|
548
|
+
'Applicant References' => (!applicant_references_required? || applicant_references.count(&:completed?) >= min_applicant_references)
|
549
|
+
}
|
550
|
+
else
|
551
|
+
{}
|
552
|
+
end
|
520
553
|
end
|
521
554
|
|
522
555
|
def complete!
|
@@ -16,6 +16,10 @@ module EffectiveMembershipsCategory
|
|
16
16
|
module ClassMethods
|
17
17
|
def effective_memberships_category?; true; end
|
18
18
|
|
19
|
+
def category_types
|
20
|
+
['Individual', 'Organization']
|
21
|
+
end
|
22
|
+
|
19
23
|
def categories
|
20
24
|
[]
|
21
25
|
end
|
@@ -35,6 +39,8 @@ module EffectiveMembershipsCategory
|
|
35
39
|
has_many :membership_categories, class_name: 'Effective::MembershipCategory', as: :category
|
36
40
|
|
37
41
|
effective_resource do
|
42
|
+
category_type :string
|
43
|
+
|
38
44
|
title :string
|
39
45
|
category :string
|
40
46
|
position :integer
|
@@ -110,17 +116,18 @@ module EffectiveMembershipsCategory
|
|
110
116
|
scope :create_bad_standing, -> { where(create_bad_standing: true) }
|
111
117
|
|
112
118
|
validates :title, presence: true, uniqueness: true
|
113
|
-
|
119
|
+
validates :category_type, presence: true
|
114
120
|
validates :position, presence: true
|
115
121
|
|
116
|
-
|
117
|
-
self.applicant_wizard_steps = EffectiveMemberships.Applicant.all_wizard_steps
|
118
|
-
self.applicant_review_wizard_steps = EffectiveMemberships.ApplicantReview.all_wizard_steps
|
119
|
-
self.fee_payment_wizard_steps = EffectiveMemberships.FeePayment.all_wizard_steps
|
122
|
+
before_validation do
|
123
|
+
self.applicant_wizard_steps = EffectiveMemberships.Applicant.all_wizard_steps if applicant_wizard_steps.blank?
|
124
|
+
self.applicant_review_wizard_steps = EffectiveMemberships.ApplicantReview.all_wizard_steps if applicant_review_wizard_steps.blank?
|
125
|
+
self.fee_payment_wizard_steps = EffectiveMemberships.FeePayment.all_wizard_steps if fee_payment_wizard_steps.blank?
|
120
126
|
end
|
121
127
|
|
122
128
|
before_validation do
|
123
129
|
self.position ||= (self.class.pluck(:position).compact.max || -1) + 1
|
130
|
+
self.category_type ||= self.class.category_types.first
|
124
131
|
end
|
125
132
|
|
126
133
|
with_options(if: -> { can_apply? }) do
|
@@ -155,6 +162,14 @@ module EffectiveMembershipsCategory
|
|
155
162
|
can_apply_new? || can_apply_existing? || can_apply_restricted?
|
156
163
|
end
|
157
164
|
|
165
|
+
def individual?
|
166
|
+
category_type == 'Individual'
|
167
|
+
end
|
168
|
+
|
169
|
+
def organization?
|
170
|
+
category_type == 'Organization'
|
171
|
+
end
|
172
|
+
|
158
173
|
def prorated_fee(date:)
|
159
174
|
send("prorated_#{date.strftime('%b').downcase}").to_i
|
160
175
|
end
|
@@ -167,6 +182,18 @@ module EffectiveMembershipsCategory
|
|
167
182
|
Array(self[:can_apply_restricted_ids]) - [nil, '']
|
168
183
|
end
|
169
184
|
|
185
|
+
def optional_applicant_wizard_steps
|
186
|
+
applicant_wizard_steps - EffectiveMemberships.Applicant.required_wizard_steps
|
187
|
+
end
|
188
|
+
|
189
|
+
def optional_fee_payment_wizard_steps
|
190
|
+
fee_payment_wizard_steps - EffectiveMemberships.FeePayment.required_wizard_steps
|
191
|
+
end
|
192
|
+
|
193
|
+
def optional_applicant_review_wizard_steps
|
194
|
+
applicant_review_wizard_steps - EffectiveMemberships.ApplicantReview.required_wizard_steps
|
195
|
+
end
|
196
|
+
|
170
197
|
def applicant_wizard_steps
|
171
198
|
(Array(self[:applicant_wizard_steps]) - [nil, '']).map(&:to_sym)
|
172
199
|
end
|
@@ -32,7 +32,8 @@ module EffectiveMembershipsFeePayment
|
|
32
32
|
|
33
33
|
acts_as_wizard(
|
34
34
|
start: 'Start',
|
35
|
-
demographics: 'Demographics',
|
35
|
+
demographics: 'Demographics', # Individual only. Users fields.
|
36
|
+
organization: 'Organization', # Organization only. Organization fields.
|
36
37
|
declarations: 'Declarations',
|
37
38
|
summary: 'Review',
|
38
39
|
billing: 'Billing Address',
|
@@ -48,23 +49,20 @@ module EffectiveMembershipsFeePayment
|
|
48
49
|
attr_accessor :declare_code_of_ethics
|
49
50
|
attr_accessor :declare_truth
|
50
51
|
|
51
|
-
# Throwaway
|
52
|
-
attr_accessor :upgrade, :downgrade
|
53
|
-
|
54
52
|
# Application Namespace
|
55
|
-
belongs_to :
|
56
|
-
accepts_nested_attributes_for :owner
|
57
|
-
|
58
|
-
belongs_to :user, polymorphic: true, optional: true
|
53
|
+
belongs_to :user, polymorphic: true
|
59
54
|
accepts_nested_attributes_for :user
|
60
55
|
|
56
|
+
belongs_to :organization, polymorphic: true, optional: true
|
57
|
+
accepts_nested_attributes_for :organization
|
58
|
+
|
61
59
|
# Like maybe optionally it makes sense.
|
62
60
|
belongs_to :category, polymorphic: true, optional: true
|
63
61
|
|
62
|
+
# Effective Namespace
|
64
63
|
has_many :fees, -> { order(:id) }, as: :parent, class_name: 'Effective::Fee', dependent: :nullify
|
65
64
|
accepts_nested_attributes_for :fees, reject_if: :all_blank, allow_destroy: true
|
66
65
|
|
67
|
-
# Effective Namespace
|
68
66
|
has_many :orders, -> { order(:id) }, as: :parent, class_name: 'Effective::Order', dependent: :nullify
|
69
67
|
accepts_nested_attributes_for :orders
|
70
68
|
|
@@ -83,24 +81,32 @@ module EffectiveMembershipsFeePayment
|
|
83
81
|
timestamps
|
84
82
|
end
|
85
83
|
|
86
|
-
scope :deep, -> { includes(:
|
84
|
+
scope :deep, -> { includes(:user, :organization, :category, :orders) }
|
87
85
|
scope :sorted, -> { order(:id) }
|
88
86
|
|
89
87
|
scope :in_progress, -> { where.not(status: [:submitted]) }
|
90
88
|
scope :done, -> { where(status: [:submitted]) }
|
91
89
|
|
90
|
+
scope :for, -> (user) {
|
91
|
+
raise('expected a effective memberships user') unless user.class.try(:effective_memberships_user?)
|
92
|
+
where(user: user).or(where(organization: user.organizations))
|
93
|
+
}
|
94
|
+
|
92
95
|
before_validation do
|
93
96
|
self.period ||= EffectiveMemberships.Registrar.current_period
|
94
97
|
end
|
95
98
|
|
96
|
-
before_validation(if: -> { current_step == :start
|
97
|
-
self.
|
99
|
+
before_validation(if: -> { new_record? || current_step == :start }) do
|
100
|
+
self.organization_type = (EffectiveMemberships.Organization.name if organization_id.present?)
|
98
101
|
end
|
99
102
|
|
100
|
-
|
103
|
+
before_validation(if: -> { current_step == :start && user && user.membership }) do
|
104
|
+
self.category ||= user.membership.categories.first if user.membership.categories.length == 1
|
105
|
+
end
|
101
106
|
|
102
107
|
# All Steps validations
|
103
|
-
validates :
|
108
|
+
validates :user, presence: true
|
109
|
+
validates :period, presence: true
|
104
110
|
|
105
111
|
# Declarations Step
|
106
112
|
with_options(if: -> { current_step == :declarations }) do
|
@@ -121,6 +127,9 @@ module EffectiveMembershipsFeePayment
|
|
121
127
|
|
122
128
|
fee_payment_steps = Array(category&.fee_payment_wizard_steps)
|
123
129
|
|
130
|
+
fee_payment_steps.delete(:organization) unless organization?
|
131
|
+
|
132
|
+
|
124
133
|
wizard_steps.select do |step|
|
125
134
|
required_steps.include?(step) || category.blank? || fee_payment_steps.include?(step)
|
126
135
|
end
|
@@ -129,10 +138,6 @@ module EffectiveMembershipsFeePayment
|
|
129
138
|
|
130
139
|
# All Fees and Orders
|
131
140
|
# Overriding acts_as_purchasable_wizard
|
132
|
-
def outstanding_fees
|
133
|
-
owner&.outstanding_fee_payment_fees
|
134
|
-
end
|
135
|
-
|
136
141
|
def submit_fees
|
137
142
|
fees
|
138
143
|
end
|
@@ -143,7 +148,7 @@ module EffectiveMembershipsFeePayment
|
|
143
148
|
|
144
149
|
# We take over the owner's outstanding fees.
|
145
150
|
def find_or_build_submit_fees
|
146
|
-
Array(
|
151
|
+
Array(owner.outstanding_fee_payment_fees).each { |fee| fees << fee unless fees.include?(fee) }
|
147
152
|
submit_fees
|
148
153
|
end
|
149
154
|
|
@@ -157,6 +162,26 @@ module EffectiveMembershipsFeePayment
|
|
157
162
|
'Fee Payment'
|
158
163
|
end
|
159
164
|
|
165
|
+
def owner
|
166
|
+
organization || user
|
167
|
+
end
|
168
|
+
|
169
|
+
def owner_symbol
|
170
|
+
organization? ? :organization : :user
|
171
|
+
end
|
172
|
+
|
173
|
+
def build_organization(params = {})
|
174
|
+
self.organization = EffectiveMemberships.Organization.new(params)
|
175
|
+
end
|
176
|
+
|
177
|
+
def individual?
|
178
|
+
!owner.kind_of?(EffectiveMemberships.Organization)
|
179
|
+
end
|
180
|
+
|
181
|
+
def organization?
|
182
|
+
owner.kind_of?(EffectiveMemberships.Organization)
|
183
|
+
end
|
184
|
+
|
160
185
|
# Instance Methods
|
161
186
|
def in_progress?
|
162
187
|
draft?
|
@@ -175,30 +200,4 @@ module EffectiveMembershipsFeePayment
|
|
175
200
|
save!
|
176
201
|
end
|
177
202
|
|
178
|
-
# Work with effective_organizations
|
179
|
-
def organization!
|
180
|
-
if upgrade_individual_to_organization?
|
181
|
-
save!
|
182
|
-
update!(owner: owner.representatives.first.organization)
|
183
|
-
elsif downgrade_organization_to_individual?
|
184
|
-
save!
|
185
|
-
update!(owner: current_user)
|
186
|
-
else
|
187
|
-
save!
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
def upgrade_individual_to_organization?
|
192
|
-
return false unless EffectiveResources.truthy?(upgrade)
|
193
|
-
return false unless owner.class.respond_to?(:effective_organizations_user?)
|
194
|
-
owner.representatives.any?(&:new_record?)
|
195
|
-
end
|
196
|
-
|
197
|
-
def downgrade_organization_to_individual?
|
198
|
-
return false unless EffectiveResources.truthy?(downgrade)
|
199
|
-
return false unless owner.class.respond_to?(:effective_organizations_organization?)
|
200
|
-
return false if current_user.blank?
|
201
|
-
owner.representatives.any?(&:marked_for_destruction?)
|
202
|
-
end
|
203
|
-
|
204
203
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# EffectiveMembershipsOrganization
|
2
|
+
#
|
3
|
+
# Mark your category model with effective_memberships_organization to get all the includes
|
4
|
+
|
5
|
+
module EffectiveMembershipsOrganization
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
module Base
|
9
|
+
def effective_memberships_organization
|
10
|
+
include ::EffectiveMembershipsOrganization
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def effective_memberships_organization?; true; end
|
16
|
+
|
17
|
+
def categories
|
18
|
+
[]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
included do
|
23
|
+
effective_memberships_owner
|
24
|
+
|
25
|
+
acts_as_addressable :billing # effective_addresses
|
26
|
+
log_changes(except: [:representatives, :users]) if respond_to?(:log_changes)
|
27
|
+
|
28
|
+
# rich_text_body
|
29
|
+
# has_many_rich_texts
|
30
|
+
|
31
|
+
# App scoped
|
32
|
+
has_many :applicants, -> { order(:id) }, inverse_of: :organization, as: :organization
|
33
|
+
has_many :fee_payments, -> { order(:id) }, inverse_of: :organization, as: :organization
|
34
|
+
|
35
|
+
# Effective scoped
|
36
|
+
has_many :representatives, -> { Effective::Representative.sorted },
|
37
|
+
class_name: 'Effective::Representative', inverse_of: :organization, dependent: :delete_all
|
38
|
+
|
39
|
+
accepts_nested_attributes_for :representatives, allow_destroy: true
|
40
|
+
|
41
|
+
effective_resource do
|
42
|
+
title :string
|
43
|
+
email :string
|
44
|
+
|
45
|
+
phone :string
|
46
|
+
fax :string
|
47
|
+
website :string
|
48
|
+
|
49
|
+
category :string
|
50
|
+
|
51
|
+
notes :text
|
52
|
+
|
53
|
+
roles_mask :integer
|
54
|
+
archived :boolean
|
55
|
+
|
56
|
+
representatives_count :integer # Counter cache
|
57
|
+
|
58
|
+
timestamps
|
59
|
+
end
|
60
|
+
|
61
|
+
scope :deep, -> { includes(:representatives) }
|
62
|
+
scope :sorted, -> { order(:title) }
|
63
|
+
|
64
|
+
validates :title, presence: true, uniqueness: true
|
65
|
+
validates :email, presence: true
|
66
|
+
end
|
67
|
+
|
68
|
+
# Instance Methods
|
69
|
+
def to_s
|
70
|
+
title.presence || 'organization'
|
71
|
+
end
|
72
|
+
|
73
|
+
def membership_present?
|
74
|
+
membership.present? && !membership.marked_for_destruction?
|
75
|
+
end
|
76
|
+
|
77
|
+
def outstanding_fee_payment_fees
|
78
|
+
fees.select { |fee| fee.fee_payment_fee? && !fee.purchased? }
|
79
|
+
end
|
80
|
+
|
81
|
+
def representative(user:)
|
82
|
+
representatives.find { |rep| rep.user_id == user.id }
|
83
|
+
end
|
84
|
+
|
85
|
+
# Find or build
|
86
|
+
def build_representative(user:)
|
87
|
+
representative(user: user) || representatives.build(user: user)
|
88
|
+
end
|
89
|
+
|
90
|
+
def users
|
91
|
+
representatives.reject(&:marked_for_destruction?).map(&:user)
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
@@ -23,10 +23,6 @@ module EffectiveMembershipsOwner
|
|
23
23
|
included do
|
24
24
|
acts_as_role_restricted unless respond_to?(:acts_as_role_restricted?)
|
25
25
|
|
26
|
-
# App scoped
|
27
|
-
has_many :applicants, -> { order(:id) }, inverse_of: :owner, as: :owner
|
28
|
-
has_many :fee_payments, -> { order(:id) }, inverse_of: :owner, as: :owner
|
29
|
-
|
30
26
|
# Effective scoped
|
31
27
|
has_many :fees, -> { order(:id) }, inverse_of: :owner, as: :owner, class_name: 'Effective::Fee', dependent: :nullify
|
32
28
|
accepts_nested_attributes_for :fees, reject_if: :all_blank, allow_destroy: true
|
@@ -40,48 +36,9 @@ module EffectiveMembershipsOwner
|
|
40
36
|
has_many :membership_histories, -> { Effective::MembershipHistory.sorted }, inverse_of: :owner, as: :owner, class_name: 'Effective::MembershipHistory'
|
41
37
|
accepts_nested_attributes_for :membership_histories
|
42
38
|
|
43
|
-
effective_resource do
|
44
|
-
timestamps
|
45
|
-
end
|
46
|
-
|
47
39
|
scope :members, -> { joins(:membership) }
|
48
40
|
end
|
49
41
|
|
50
|
-
def effective_memberships_owner
|
51
|
-
raise('expected singular usage but there are more than one owner') if effective_memberships_owners.length > 1
|
52
|
-
effective_memberships_owners.first
|
53
|
-
end
|
54
|
-
|
55
|
-
def effective_memberships_owners
|
56
|
-
owners = organizations if self.class.respond_to?(:effective_organizations_user?)
|
57
|
-
owners = users if self.class.respond_to?(:effective_organizations_organization?)
|
58
|
-
|
59
|
-
owners = Array(owners)
|
60
|
-
.select { |owner| owner.class.respond_to?(:effective_memberships_owner?) }
|
61
|
-
.reject { |owner| owner.try(:archived?) }
|
62
|
-
|
63
|
-
owners.presence || [self]
|
64
|
-
end
|
65
|
-
|
66
|
-
# This is the calculated way of determining if an owner is a member or not.
|
67
|
-
# The correct way to check for membership is: current_user.is?(:member)
|
68
|
-
def membership_present?
|
69
|
-
individual_membership_present? || organization_membership_present?
|
70
|
-
end
|
71
|
-
|
72
|
-
def individual_membership_present?
|
73
|
-
membership.present? && !membership.marked_for_destruction?
|
74
|
-
end
|
75
|
-
|
76
|
-
def organization_membership_present?(except: nil)
|
77
|
-
return false unless self.class.respond_to?(:effective_organizations_user?)
|
78
|
-
|
79
|
-
organizations
|
80
|
-
.select { |organization| organization.class.respond_to?(:effective_memberships_owner?) }
|
81
|
-
.reject { |organization| organization.try(:archived?) }
|
82
|
-
.any? { |organization| organization != except && organization.membership_present? }
|
83
|
-
end
|
84
|
-
|
85
42
|
def assign_member_role
|
86
43
|
membership_present? ? add_role(:member) : remove_role(:member)
|
87
44
|
end
|
@@ -92,18 +49,6 @@ module EffectiveMembershipsOwner
|
|
92
49
|
save!
|
93
50
|
end
|
94
51
|
|
95
|
-
def outstanding_fee_payment_owners
|
96
|
-
effective_memberships_owners.select { |owner| !owner.membership_fees_paid? }
|
97
|
-
end
|
98
|
-
|
99
|
-
def current_fee_payment_owner
|
100
|
-
outstanding_fee_payment_owners.first || self
|
101
|
-
end
|
102
|
-
|
103
|
-
def owner_label
|
104
|
-
self.class.name.split('::').last
|
105
|
-
end
|
106
|
-
|
107
52
|
def membership_fees_paid?
|
108
53
|
outstanding_fee_payment_fees.blank? && membership && membership.fees_paid?
|
109
54
|
end
|
@@ -207,9 +207,10 @@ module EffectiveMembershipsRegistrar
|
|
207
207
|
save!(owner, date: date)
|
208
208
|
end
|
209
209
|
|
210
|
-
def fees_paid!(owner, date: nil)
|
210
|
+
def fees_paid!(owner, date: nil, order_attributes: nil)
|
211
211
|
raise('expecting a memberships owner') unless owner.class.respond_to?(:effective_memberships_owner?)
|
212
212
|
raise('expected a member') unless owner.membership.present?
|
213
|
+
raise('expected a Hash of attributes') if order_attributes.present? && !order_attributes.kind_of?(Hash)
|
213
214
|
|
214
215
|
# Date
|
215
216
|
date ||= Time.zone.now
|
@@ -219,6 +220,7 @@ module EffectiveMembershipsRegistrar
|
|
219
220
|
|
220
221
|
if owner.outstanding_fee_payment_fees.present?
|
221
222
|
order = Effective::Order.new(items: owner.outstanding_fee_payment_fees, user: owner)
|
223
|
+
order.assign_attributes(order_attributes) if order_attributes.present?
|
222
224
|
order.mark_as_purchased!
|
223
225
|
end
|
224
226
|
|
@@ -305,7 +307,7 @@ module EffectiveMembershipsRegistrar
|
|
305
307
|
def add_member_role(owner)
|
306
308
|
owner.add_role(:member)
|
307
309
|
|
308
|
-
if owner.class.respond_to?(:
|
310
|
+
if owner.class.respond_to?(:effective_memberships_organization?)
|
309
311
|
organization = owner
|
310
312
|
organization.representatives.each { |representative| representative.user.add_role(:member) }
|
311
313
|
end
|
@@ -316,7 +318,7 @@ module EffectiveMembershipsRegistrar
|
|
316
318
|
def remove_member_role(owner)
|
317
319
|
owner.remove_role(:member)
|
318
320
|
|
319
|
-
if owner.class.respond_to?(:
|
321
|
+
if owner.class.respond_to?(:effective_memberships_organization?)
|
320
322
|
organization = owner
|
321
323
|
|
322
324
|
organization.representatives.each do |representative|
|