effective_memberships 0.5.0 → 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/datatables/effective_applicant_endorsers_datatable.rb +20 -0
- data/app/models/concerns/effective_memberships_applicant.rb +99 -45
- data/app/models/concerns/effective_memberships_category.rb +9 -2
- data/app/models/concerns/effective_memberships_fee_payment.rb +16 -6
- data/app/models/concerns/effective_memberships_registrar.rb +20 -1
- data/app/models/concerns/effective_memberships_user.rb +4 -0
- data/app/models/effective/applicant_endorsement.rb +3 -0
- data/app/models/effective/fee.rb +11 -3
- data/app/views/effective/applicant_endorsers/_dashboard.html.haml +10 -0
- data/app/views/effective/applicants/_reinstatement.html.haml +9 -0
- data/app/views/effective/applicants/reinstatement.html.haml +15 -0
- data/app/views/effective/applicants/select/_apply_for_reinstatement.html.haml +3 -0
- data/app/views/effective/applicants/select/_apply_to_join.html.haml +1 -0
- data/app/views/effective/applicants/select/_apply_to_reclassify.html.haml +5 -0
- data/app/views/effective/applicants/select/_categories.html.haml +25 -0
- data/app/views/effective/applicants/select.html.haml +34 -26
- data/db/migrate/01_create_effective_memberships.rb.erb +7 -0
- data/db/seeds.rb +6 -0
- data/lib/effective_memberships/version.rb +1 -1
- data/lib/effective_memberships.rb +1 -1
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20013e5735497e62dd4c8224ef8fe0a97f9cc12d285871541cea4ceaefa13796
|
4
|
+
data.tar.gz: 0b652f51e8b7ac62c99c11b7a6a5fe6961e8b79a579048aaa7e06b8ad5dca204
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bde5324d4cadb8f64caca5fa6cc8eb0910015514df5bcad58170a78be4e27e736fcbd1d306b3fa19f919a49183d4a0e940b82b17d2f7401d6d87927b5c9a36b6
|
7
|
+
data.tar.gz: b3cd7c41dc00b22804ab6e8df8904807b0099758ce479807f682e2686cd5c64362fd0be534af0181868a29f8c2935e4f7dd7c72d6b1d2f3e56f78ebcc543d2c2
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# For the Endorser's dashboard to display endorsements to complete
|
2
|
+
class EffectiveApplicantEndorsersDatatable < Effective::Datatable
|
3
|
+
|
4
|
+
datatable do
|
5
|
+
length :all
|
6
|
+
|
7
|
+
col :created_at
|
8
|
+
col :applicant
|
9
|
+
|
10
|
+
actions_col do |applicant_endorsement|
|
11
|
+
dropdown_link_to 'Show', effective_memberships.applicant_endorsement_path(applicant_endorsement)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
collection do
|
17
|
+
Effective::ApplicantEndorsement.deep.needs_endorser.where(endorser: current_user)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -22,7 +22,7 @@ module EffectiveMembershipsApplicant
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def categories
|
25
|
-
['Apply to Join', 'Apply to Reclassify']
|
25
|
+
['Apply to Join', 'Apply to Reclassify', 'Apply for Reinstatement']
|
26
26
|
end
|
27
27
|
|
28
28
|
def transcripts_statuses
|
@@ -51,6 +51,7 @@ module EffectiveMembershipsApplicant
|
|
51
51
|
select: 'Select Application Type',
|
52
52
|
demographics: 'Demographics', # Individual only. Users fields.
|
53
53
|
organization: 'Organization', # Organization only. Organization fields.
|
54
|
+
reinstatement: 'Reinstatement', # Apply for Reinstatement only
|
54
55
|
education: 'Education',
|
55
56
|
course_amounts: 'Courses',
|
56
57
|
equivalences: 'Equivalent Memberships',
|
@@ -80,6 +81,9 @@ module EffectiveMembershipsApplicant
|
|
80
81
|
attr_accessor :declare_code_of_ethics
|
81
82
|
attr_accessor :declare_truth
|
82
83
|
|
84
|
+
# Reinstatements Step
|
85
|
+
attr_accessor :declare_reinstatement
|
86
|
+
|
83
87
|
# Admin Approve Step
|
84
88
|
attr_accessor :approved_membership_number
|
85
89
|
attr_accessor :approved_membership_date
|
@@ -93,7 +97,10 @@ module EffectiveMembershipsApplicant
|
|
93
97
|
|
94
98
|
belongs_to :category, polymorphic: true, optional: true
|
95
99
|
|
100
|
+
# Required for Apply to Reclassify
|
96
101
|
belongs_to :from_category, polymorphic: true, optional: true
|
102
|
+
|
103
|
+
# Required for Apply for Reinstatement
|
97
104
|
belongs_to :from_status, polymorphic: true, optional: true
|
98
105
|
|
99
106
|
has_many :applicant_reviews, -> { order(:id) }, as: :applicant, inverse_of: :applicant, dependent: :destroy
|
@@ -171,7 +178,7 @@ module EffectiveMembershipsApplicant
|
|
171
178
|
timestamps
|
172
179
|
end
|
173
180
|
|
174
|
-
scope :deep, -> { includes(:user, :organization, :category, :from_category, :orders) }
|
181
|
+
scope :deep, -> { includes(:user, :organization, :category, :from_category, :from_status, :orders) }
|
175
182
|
scope :sorted, -> { order(:id) }
|
176
183
|
|
177
184
|
scope :in_progress, -> { where.not(status: [:approved, :declined]) }
|
@@ -186,7 +193,7 @@ module EffectiveMembershipsApplicant
|
|
186
193
|
|
187
194
|
# Set Apply to Join or Reclassification
|
188
195
|
before_validation(if: -> { (new_record? || current_step == :select) && owner.present? }) do
|
189
|
-
self.applicant_type
|
196
|
+
self.applicant_type ||= can_apply_applicant_types_collection().first
|
190
197
|
self.from_category = owner.membership&.category
|
191
198
|
self.from_status = owner.membership&.status
|
192
199
|
end
|
@@ -197,12 +204,18 @@ module EffectiveMembershipsApplicant
|
|
197
204
|
|
198
205
|
# All Steps validations
|
199
206
|
validates :user, presence: true
|
207
|
+
|
200
208
|
validates :from_category, presence: true, if: -> { reclassification? }
|
209
|
+
validates :from_status, presence: true, if: -> { reinstatement? }
|
201
210
|
|
202
|
-
validate(if: -> { reclassification? }) do
|
211
|
+
validate(if: -> { reclassification? && category_id.present? }) do
|
203
212
|
errors.add(:category_id, "can't reclassify to existing category") if category_id == from_category_id
|
204
213
|
end
|
205
214
|
|
215
|
+
validate(if: -> { reinstatement? && category_id.present? }) do
|
216
|
+
errors.add(:category_id, "must match existing category when reinstatement") unless category_id == from_category_id
|
217
|
+
end
|
218
|
+
|
206
219
|
validate(if: -> { category.present? }) do
|
207
220
|
self.errors.add(:organization_id, "can't be blank when organization category") if category.organization? && organization.blank?
|
208
221
|
self.errors.add(:organization_id, "must be blank when individual category") if category.individual? && organization.present?
|
@@ -315,6 +328,12 @@ module EffectiveMembershipsApplicant
|
|
315
328
|
validates :declare_truth, acceptance: true
|
316
329
|
end
|
317
330
|
|
331
|
+
# Reinstatements step
|
332
|
+
with_options(if: -> { current_step == :reinstatement }) do
|
333
|
+
validates :declare_reinstatement, acceptance: true
|
334
|
+
end
|
335
|
+
|
336
|
+
|
318
337
|
# Admin Approve
|
319
338
|
validate(if: -> { approved_membership_date.present? }) do
|
320
339
|
if approved_membership_date.to_date > Time.zone.now.to_date
|
@@ -340,16 +359,19 @@ module EffectiveMembershipsApplicant
|
|
340
359
|
# This required_steps is defined inside the included do .. end block so it overrides the acts_as_wizard one.
|
341
360
|
def required_steps
|
342
361
|
return self.class.test_required_steps if Rails.env.test? && self.class.test_required_steps.present?
|
362
|
+
return self.class.all_wizard_steps if category.blank?
|
343
363
|
|
344
364
|
@_required_steps ||= begin
|
345
|
-
|
365
|
+
# All required
|
346
366
|
required_steps = self.class.required_wizard_steps
|
347
367
|
|
348
|
-
|
368
|
+
# Based on current applicant
|
369
|
+
applicant_steps = (reinstatement? ? category.applicant_reinstatement_wizard_steps : category.applicant_wizard_steps)
|
349
370
|
|
350
|
-
#
|
371
|
+
# Sanity check
|
351
372
|
applicant_steps.delete(:stamp) unless apply_to_join?
|
352
373
|
applicant_steps.delete(:organization) unless category&.organization?
|
374
|
+
applicant_steps.delete(:reinstatement) unless reinstatement?
|
353
375
|
|
354
376
|
# change_wizard_steps is defined in effective_resources acts_as_wizard
|
355
377
|
applicant_steps = change_wizard_steps(applicant_steps)
|
@@ -358,44 +380,63 @@ module EffectiveMembershipsApplicant
|
|
358
380
|
raise('expected change_wizard_steps to return an Array of steps with no nils')
|
359
381
|
end
|
360
382
|
|
361
|
-
|
362
|
-
required_steps.include?(step) ||
|
383
|
+
self.class.all_wizard_steps.select do |step|
|
384
|
+
required_steps.include?(step) || applicant_steps.include?(step)
|
363
385
|
end
|
364
386
|
end
|
365
387
|
end
|
366
388
|
|
367
389
|
def sidebar_steps
|
368
|
-
|
369
|
-
required_steps
|
390
|
+
has_completed_step?(:select) ? required_steps : self.class.required_wizard_steps
|
370
391
|
end
|
371
392
|
|
372
393
|
def can_visit_step?(step)
|
373
|
-
if missing_info?
|
374
|
-
return [:start, :select, :billing, :checkout].exclude?(step)
|
375
|
-
end
|
376
|
-
|
394
|
+
return [:start, :select, :billing, :checkout].exclude?(step) if missing_info?
|
377
395
|
can_revisit_completed_steps(step)
|
378
396
|
end
|
379
397
|
|
398
|
+
# Find fee
|
399
|
+
def fee(fee_type:)
|
400
|
+
fees.find { |fee| fee.fee_type == fee_type }
|
401
|
+
end
|
402
|
+
|
403
|
+
# Find or build
|
404
|
+
def build_fee(fee_type:)
|
405
|
+
fee(fee_type: fee_type) || fees.build(parent: self, owner: owner, fee_type: fee_type)
|
406
|
+
end
|
407
|
+
|
408
|
+
def applicant_fee_type
|
409
|
+
return 'Reinstatement' if reinstatement?
|
410
|
+
'Applicant'
|
411
|
+
end
|
412
|
+
|
380
413
|
def applicant_fee_category
|
381
414
|
category
|
382
415
|
end
|
383
416
|
|
384
417
|
def applicant_fee_price
|
418
|
+
return category.applicant_reinstatement_fee if reinstatement?
|
385
419
|
category.applicant_fee
|
386
420
|
end
|
387
421
|
|
388
422
|
# All Fees and Orders
|
389
423
|
def submit_fees
|
424
|
+
default_applicant_submit_fees
|
425
|
+
end
|
426
|
+
|
427
|
+
def default_applicant_submit_fees
|
390
428
|
# Find or build submit fee
|
391
|
-
fee = fees.first ||
|
429
|
+
fee = fees.first || build_fee(fee_type: applicant_fee_type)
|
430
|
+
|
431
|
+
raise('expected a present applicant fee price') if applicant_fee_price.blank?
|
392
432
|
|
393
433
|
unless fee.purchased?
|
394
434
|
fee.assign_attributes(
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
435
|
+
fee_type: applicant_fee_type,
|
436
|
+
category: applicant_fee_category,
|
437
|
+
price: applicant_fee_price,
|
438
|
+
tax_exempt: applicant_fee_category.applicant_fee_tax_exempt,
|
439
|
+
qb_item_name: applicant_fee_category.applicant_fee_qb_item_name
|
399
440
|
)
|
400
441
|
end
|
401
442
|
|
@@ -436,18 +477,9 @@ module EffectiveMembershipsApplicant
|
|
436
477
|
|
437
478
|
# Instance Methods
|
438
479
|
def to_s
|
439
|
-
if
|
440
|
-
|
441
|
-
|
442
|
-
'-',
|
443
|
-
category,
|
444
|
-
'for',
|
445
|
-
category,
|
446
|
-
("from #{from_category}" if reclassification?)
|
447
|
-
].compact.join(' ')
|
448
|
-
else
|
449
|
-
'New Applicant'
|
450
|
-
end
|
480
|
+
return 'New Applicant' if applicant_type.blank? || category.blank? || owner.blank?
|
481
|
+
|
482
|
+
"#{owner} - #{applicant_type} to #{category}"
|
451
483
|
end
|
452
484
|
|
453
485
|
def owner
|
@@ -470,6 +502,10 @@ module EffectiveMembershipsApplicant
|
|
470
502
|
applicant_type == 'Apply to Reclassify'
|
471
503
|
end
|
472
504
|
|
505
|
+
def reinstatement?
|
506
|
+
applicant_type == 'Apply for Reinstatement'
|
507
|
+
end
|
508
|
+
|
473
509
|
def individual?
|
474
510
|
!(owner.kind_of?(EffectiveMemberships.Organization) && category&.organization?)
|
475
511
|
end
|
@@ -519,6 +555,17 @@ module EffectiveMembershipsApplicant
|
|
519
555
|
end.html_safe
|
520
556
|
end
|
521
557
|
|
558
|
+
# Used by the select step
|
559
|
+
def can_apply_applicant_types_collection
|
560
|
+
if owner.blank? || owner.membership.blank? || owner.membership.categories.blank?
|
561
|
+
['Apply to Join']
|
562
|
+
elsif owner.membership.statuses.present?
|
563
|
+
['Apply for Reinstatement', 'Apply to Join']
|
564
|
+
else
|
565
|
+
['Apply to Reclassify']
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
522
569
|
# Used by the select step
|
523
570
|
def can_apply_categories_collection
|
524
571
|
categories = EffectiveMemberships.Category.sorted.can_apply
|
@@ -527,7 +574,7 @@ module EffectiveMembershipsApplicant
|
|
527
574
|
return categories.where(can_apply_new: true)
|
528
575
|
end
|
529
576
|
|
530
|
-
category_ids = user.
|
577
|
+
category_ids = user.membership.category_ids
|
531
578
|
|
532
579
|
categories.select do |cat|
|
533
580
|
cat.can_apply_existing? ||
|
@@ -587,7 +634,7 @@ module EffectiveMembershipsApplicant
|
|
587
634
|
end
|
588
635
|
|
589
636
|
def applicant_references_required?
|
590
|
-
min_applicant_references > 0
|
637
|
+
required_steps.include?(:references) && min_applicant_references > 0
|
591
638
|
end
|
592
639
|
|
593
640
|
# Endorsements Step
|
@@ -596,7 +643,7 @@ module EffectiveMembershipsApplicant
|
|
596
643
|
end
|
597
644
|
|
598
645
|
def applicant_endorsements_required?
|
599
|
-
min_applicant_endorsements > 0
|
646
|
+
required_steps.include?(:endorsements) && min_applicant_endorsements > 0
|
600
647
|
end
|
601
648
|
|
602
649
|
# Equivalences Step
|
@@ -610,7 +657,7 @@ module EffectiveMembershipsApplicant
|
|
610
657
|
end
|
611
658
|
|
612
659
|
def transcripts_required?
|
613
|
-
|
660
|
+
required_steps.include?(:transcripts)
|
614
661
|
end
|
615
662
|
|
616
663
|
# Files Step
|
@@ -634,16 +681,16 @@ module EffectiveMembershipsApplicant
|
|
634
681
|
requirements = {}
|
635
682
|
return requirements unless category.present?
|
636
683
|
|
637
|
-
if
|
638
|
-
requirements['Applicant Endorsements'] = (
|
684
|
+
if applicant_endorsements_required?
|
685
|
+
requirements['Applicant Endorsements'] = (applicant_endorsements.count(&:completed?) >= min_applicant_endorsements)
|
639
686
|
end
|
640
687
|
|
641
|
-
if
|
642
|
-
requirements['Applicant References'] = (
|
688
|
+
if applicant_references_required?
|
689
|
+
requirements['Applicant References'] = (applicant_references.count(&:completed?) >= min_applicant_references)
|
643
690
|
end
|
644
691
|
|
645
|
-
if
|
646
|
-
requirements['Applicant Transcripts'] =
|
692
|
+
if transcripts_required?
|
693
|
+
requirements['Applicant Transcripts'] = transcripts_received?
|
647
694
|
end
|
648
695
|
|
649
696
|
requirements
|
@@ -692,9 +739,14 @@ module EffectiveMembershipsApplicant
|
|
692
739
|
# When an application is completed, these must be done to go to reviewed
|
693
740
|
# An Admin can override this and just set them to reviewed.
|
694
741
|
def reviewed_requirements
|
695
|
-
{
|
696
|
-
|
697
|
-
|
742
|
+
requirements = {}
|
743
|
+
return requirements unless category.present?
|
744
|
+
|
745
|
+
if applicant_reviews_required?
|
746
|
+
requirements['Applicant Reviews'] = (applicant_reviews.count(&:completed?) >= min_applicant_reviews)
|
747
|
+
end
|
748
|
+
|
749
|
+
requirements
|
698
750
|
end
|
699
751
|
|
700
752
|
def review!
|
@@ -726,6 +778,8 @@ module EffectiveMembershipsApplicant
|
|
726
778
|
)
|
727
779
|
elsif reclassification?
|
728
780
|
EffectiveMemberships.Registrar.reclassify!(owner, to: category)
|
781
|
+
elsif reinstatement?
|
782
|
+
EffectiveMemberships.Registrar.reinstate!(owner)
|
729
783
|
else
|
730
784
|
raise('unsupported approval applicant_type')
|
731
785
|
end
|
@@ -51,8 +51,9 @@ module EffectiveMembershipsCategory
|
|
51
51
|
can_apply_restricted :boolean
|
52
52
|
can_apply_restricted_ids :text
|
53
53
|
|
54
|
-
applicant_fee
|
55
|
-
|
54
|
+
applicant_fee :integer
|
55
|
+
applicant_reinstatement_fee :integer
|
56
|
+
applicant_wizard_steps :text
|
56
57
|
|
57
58
|
min_applicant_educations :integer
|
58
59
|
min_applicant_endorsements :integer
|
@@ -192,10 +193,16 @@ module EffectiveMembershipsCategory
|
|
192
193
|
applicant_review_wizard_steps - EffectiveMemberships.ApplicantReview.required_wizard_steps
|
193
194
|
end
|
194
195
|
|
196
|
+
# Apply to Join or Apply to Reclassify
|
195
197
|
def applicant_wizard_steps
|
196
198
|
(Array(self[:applicant_wizard_steps]) - [nil, '']).map(&:to_sym)
|
197
199
|
end
|
198
200
|
|
201
|
+
# Apply for Reinstatement
|
202
|
+
def applicant_reinstatement_wizard_steps
|
203
|
+
[:reinstatement]
|
204
|
+
end
|
205
|
+
|
199
206
|
def fee_payment_wizard_steps
|
200
207
|
(Array(self[:fee_payment_wizard_steps]) - [nil, '']).map(&:to_sym)
|
201
208
|
end
|
@@ -57,7 +57,7 @@ module EffectiveMembershipsFeePayment
|
|
57
57
|
accepts_nested_attributes_for :organization
|
58
58
|
|
59
59
|
belongs_to :category, polymorphic: true, optional: true
|
60
|
-
belongs_to :
|
60
|
+
belongs_to :with_status, polymorphic: true, optional: true
|
61
61
|
|
62
62
|
# Effective Namespace
|
63
63
|
has_many :fees, -> { order(:id) }, as: :parent, class_name: 'Effective::Fee', dependent: :nullify
|
@@ -102,7 +102,7 @@ module EffectiveMembershipsFeePayment
|
|
102
102
|
|
103
103
|
before_validation(if: -> { current_step == :start && user && user.membership }) do
|
104
104
|
self.category ||= user.membership.categories.first if user.membership.categories.length == 1
|
105
|
-
self.
|
105
|
+
self.with_status ||= user.membership.statuses.first if user.membership.statuses.length == 1
|
106
106
|
end
|
107
107
|
|
108
108
|
# All Steps validations
|
@@ -121,17 +121,27 @@ module EffectiveMembershipsFeePayment
|
|
121
121
|
# This required_steps is defined inside the included do .. end block so it overrides the acts_as_wizard one.
|
122
122
|
def required_steps
|
123
123
|
return self.class.test_required_steps if Rails.env.test? && self.class.test_required_steps.present?
|
124
|
+
return self.class.all_wizard_steps if category.blank?
|
124
125
|
|
125
126
|
@_required_steps ||= begin
|
126
|
-
|
127
|
+
# All required
|
127
128
|
required_steps = self.class.required_wizard_steps
|
128
129
|
|
129
|
-
|
130
|
+
# Based on current fee payment
|
131
|
+
fee_payment_steps = Array(category.fee_payment_wizard_steps)
|
130
132
|
|
133
|
+
# Sanity Check
|
131
134
|
fee_payment_steps.delete(:organization) unless organization?
|
132
135
|
|
133
|
-
|
134
|
-
|
136
|
+
# change_wizard_steps is defined in effective_resources acts_as_wizard
|
137
|
+
fee_payment_steps = change_wizard_steps(fee_payment_steps)
|
138
|
+
|
139
|
+
unless fee_payment_steps.kind_of?(Array) && fee_payment_steps.all? { |step| step.kind_of?(Symbol) }
|
140
|
+
raise('expected change_wizard_steps to return an Array of steps with no nils')
|
141
|
+
end
|
142
|
+
|
143
|
+
self.class.all_wizard_steps.select do |step|
|
144
|
+
required_steps.include?(step) || fee_payment_steps.include?(step)
|
135
145
|
end
|
136
146
|
end
|
137
147
|
end
|
@@ -155,7 +155,6 @@ module EffectiveMembershipsRegistrar
|
|
155
155
|
raise('expecting a memberships owner') unless owner.class.respond_to?(:effective_memberships_owner?)
|
156
156
|
raise('owner must have an existing membership. use register! instead') if owner.membership.blank?
|
157
157
|
|
158
|
-
# Todo. I dunno this was owner.membership.category
|
159
158
|
from = owner.membership.category
|
160
159
|
|
161
160
|
raise('expecting a to memberships category') unless to.class.respond_to?(:effective_memberships_category?)
|
@@ -183,6 +182,26 @@ module EffectiveMembershipsRegistrar
|
|
183
182
|
save!(owner, date: date)
|
184
183
|
end
|
185
184
|
|
185
|
+
def reinstate!(owner, date: nil, skip_fees: false)
|
186
|
+
raise('expecting a memberships owner') unless owner.class.respond_to?(:effective_memberships_owner?)
|
187
|
+
raise('owner must have an existing membership. use register! instead') if owner.membership.blank?
|
188
|
+
|
189
|
+
from = owner.membership.status
|
190
|
+
raise('expecting a from memberships status') if from.present? && !from.class.respond_to?(:effective_memberships_status?)
|
191
|
+
|
192
|
+
date ||= Time.zone.now
|
193
|
+
|
194
|
+
membership = owner.membership
|
195
|
+
membership.membership_status(status: from).mark_for_destruction if from.present?
|
196
|
+
|
197
|
+
unless skip_fees
|
198
|
+
fee = owner.build_prorated_fee(date: date)
|
199
|
+
# This might already be present and purchased if joined and reinstated in the same period
|
200
|
+
end
|
201
|
+
|
202
|
+
save!(owner, date: date)
|
203
|
+
end
|
204
|
+
|
186
205
|
# This clears the status entirely from user
|
187
206
|
def status_remove!(owner, date: nil)
|
188
207
|
status_change!(owner, to: nil, date: date)
|
@@ -28,6 +28,10 @@ module EffectiveMembershipsUser
|
|
28
28
|
|
29
29
|
accepts_nested_attributes_for :representatives, allow_destroy: true
|
30
30
|
|
31
|
+
# I'm an endorser for these
|
32
|
+
has_many :applicant_endorsements, -> { Effective::ApplicantEndorsement.sorted },
|
33
|
+
class_name: 'Effective::ApplicantEndorsement', inverse_of: :endorser, as: :endorser, dependent: :nullify
|
34
|
+
|
31
35
|
scope :membership_applying, -> {
|
32
36
|
applicants = EffectiveMemberships.Applicant.all
|
33
37
|
without_role(:member).where(id: applicants.select(:user_id))
|
@@ -39,6 +39,9 @@ module Effective
|
|
39
39
|
end
|
40
40
|
|
41
41
|
scope :deep, -> { all }
|
42
|
+
scope :sorted, -> { order(:id) }
|
43
|
+
|
44
|
+
scope :needs_endorser, -> { where(status: :submitted).where(applicant_id: EffectiveMemberships.Applicant.not_draft) }
|
42
45
|
|
43
46
|
# All step validations
|
44
47
|
validates :applicant, presence: true
|
data/app/models/effective/fee.rb
CHANGED
@@ -13,6 +13,9 @@ module Effective
|
|
13
13
|
# The membership category for this fee, if there's only 1 membership.categories
|
14
14
|
belongs_to :category, polymorphic: true, optional: true
|
15
15
|
|
16
|
+
# The membership status for this fee, if there's only 1 membership.statuses
|
17
|
+
belongs_to :with_status, polymorphic: true, optional: true
|
18
|
+
|
16
19
|
effective_resource do
|
17
20
|
fee_type :string
|
18
21
|
|
@@ -35,6 +38,7 @@ module Effective
|
|
35
38
|
|
36
39
|
before_validation(if: -> { owner && owner.membership }) do
|
37
40
|
self.category ||= owner.membership.categories.first if owner.membership.categories.length == 1
|
41
|
+
self.with_status ||= owner.membership.statuses.first if owner.membership.statuses.length == 1
|
38
42
|
end
|
39
43
|
|
40
44
|
before_validation do
|
@@ -81,16 +85,20 @@ module Effective
|
|
81
85
|
|
82
86
|
# Used by applicant.applicant_submit_fees
|
83
87
|
def applicant_submit_fee?
|
84
|
-
|
88
|
+
return true if parent.kind_of?(EffectiveMemberships.Applicant)
|
89
|
+
|
90
|
+
['Applicant', 'Reinstatement'].include?(fee_type)
|
85
91
|
end
|
86
92
|
|
87
93
|
def fee_payment_fee?
|
88
|
-
|
94
|
+
return false if parent.kind_of?(EffectiveMemberships.Applicant)
|
95
|
+
|
96
|
+
['Applicant', 'Reinstatement'].exclude?(fee_type)
|
89
97
|
end
|
90
98
|
|
91
99
|
# Will advance a membership.fees_paid_through_year value when purchased
|
92
100
|
def membership_period_fee?
|
93
|
-
|
101
|
+
['Prorated', 'Renewal'].include?(fee_type)
|
94
102
|
end
|
95
103
|
|
96
104
|
def custom_fee?
|
@@ -0,0 +1,10 @@
|
|
1
|
+
- datatable = EffectiveApplicantEndorsersDatatable.new(self, endorser: current_user)
|
2
|
+
|
3
|
+
%h2 Endorsements
|
4
|
+
|
5
|
+
- if datatable.present?
|
6
|
+
%p Your endorsement has been requested on the following applicants:
|
7
|
+
= render_simple_datatable(datatable)
|
8
|
+
|
9
|
+
- else
|
10
|
+
%p There are no applicant endorsements to complete.
|
@@ -0,0 +1,9 @@
|
|
1
|
+
= wizard_card(applicant) do
|
2
|
+
%table.table.table-sm
|
3
|
+
%tbody
|
4
|
+
%tr
|
5
|
+
%td= icon('check')
|
6
|
+
%td Yes, I am applying to reinstate from #{applicant.from_status || applicant.from_category}.
|
7
|
+
%tr
|
8
|
+
%td= icon('check')
|
9
|
+
%td Yes, I have read, understand and agree to the reinstatement declaration
|
@@ -0,0 +1,15 @@
|
|
1
|
+
= render 'layout' do
|
2
|
+
= render 'effective/applicants/content', resource: resource
|
3
|
+
|
4
|
+
- completed = resource.has_completed_step?(:reinstatement)
|
5
|
+
- resource.declare_reinstatement = completed
|
6
|
+
|
7
|
+
= card do
|
8
|
+
= effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
|
9
|
+
= f.hidden_field :id
|
10
|
+
|
11
|
+
= render_if_exists("effective/applicants/reinstatement_fields", f: f)
|
12
|
+
|
13
|
+
= f.check_box :declare_reinstatement, label: 'Yes, I accept and agree to the above'
|
14
|
+
|
15
|
+
= f.save 'Save and Continue'
|
@@ -0,0 +1 @@
|
|
1
|
+
%p Please select a category for your application to join:
|
@@ -0,0 +1,25 @@
|
|
1
|
+
- organization_categories = categories.select(&:organization?)
|
2
|
+
|
3
|
+
- if categories.blank?
|
4
|
+
%p
|
5
|
+
There are no categories available for you to apply for.
|
6
|
+
Please contact us if you believe this is in error.
|
7
|
+
|
8
|
+
- if categories.present?
|
9
|
+
= f.select :category_id, categories, required: true
|
10
|
+
|
11
|
+
- categories.each do |mc|
|
12
|
+
= f.show_if(:category_id, mc.id) do
|
13
|
+
.mb-4
|
14
|
+
%h3= mc.to_s
|
15
|
+
|
16
|
+
- if organization_categories.present?
|
17
|
+
%small.text-muted #{mc.category} #{mc.category_type} Membership
|
18
|
+
|
19
|
+
= mc.rich_text_body
|
20
|
+
|
21
|
+
= render_if_exists("effective/applicants/select/#{mc.to_s.parameterize.underscore}", f: f, category: mc)
|
22
|
+
|
23
|
+
- if organization_categories.present?
|
24
|
+
= f.show_if_any(:category_id, organization_categories.map(&:id)) do
|
25
|
+
= render('effective/applicants/select_organization', f: f)
|
@@ -2,41 +2,49 @@
|
|
2
2
|
= render 'effective/applicants/content', resource: resource
|
3
3
|
|
4
4
|
- categories = resource.can_apply_categories_collection()
|
5
|
-
-
|
5
|
+
- applicant_types = resource.can_apply_applicant_types_collection()
|
6
|
+
- existing_category = resource.owner&.membership&.category
|
6
7
|
|
7
8
|
= card do
|
8
|
-
|
9
|
-
|
10
|
-
There are no categories available for you to apply for.
|
11
|
-
Please contact us if you believe this is in error.
|
9
|
+
= effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
|
10
|
+
= f.hidden_field :id
|
12
11
|
|
13
|
-
|
14
|
-
|
12
|
+
= f.hidden_field :stream, value: nil
|
13
|
+
= f.hidden_field :organization_id, value: nil
|
14
|
+
= f.hidden_field :organization_type, value: nil
|
15
15
|
|
16
|
-
=
|
17
|
-
|
16
|
+
= f.hidden_field :applicant_type, value: applicant_types.first
|
17
|
+
= f.hidden_field :category_type, value: EffectiveMemberships.Category.name
|
18
18
|
|
19
|
-
|
20
|
-
=
|
21
|
-
= f
|
22
|
-
= f.hidden_field :category_type, value: EffectiveMemberships.Category.name
|
19
|
+
- if applicant_types == ['Apply to Join']
|
20
|
+
= render('effective/applicants/select/apply_to_join', f: f)
|
21
|
+
= render('effective/applicants/select/categories', f: f, categories: categories)
|
23
22
|
|
24
|
-
|
23
|
+
- elsif applicant_types == ['Apply for Reinstatement']
|
24
|
+
= f.hidden_field :applicant_type, value: applicant_types.first
|
25
|
+
= f.hidden_field :category_id, value: existing_category.id
|
26
|
+
= render('effective/applicants/select/apply_for_reinstatement', f: f)
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
%h3= mc.to_s
|
28
|
+
- elsif applicant_types == ['Apply to Reclassify']
|
29
|
+
= render('effective/applicants/select/apply_to_reclassify', f: f)
|
30
|
+
= render('effective/applicants/select/categories', f: f, categories: categories - [existing_category])
|
30
31
|
|
31
|
-
|
32
|
-
|
32
|
+
- else
|
33
|
+
= f.select :applicant_type, applicant_types, label: 'Apply to...'
|
33
34
|
|
34
|
-
|
35
|
+
- if applicant_types.include?('Apply to Join')
|
36
|
+
= f.show_if :applicant_type, 'Apply to Join' do
|
37
|
+
= render('effective/applicants/select/apply_to_join', f: f)
|
38
|
+
= render('effective/applicants/select/categories', f: f, categories: categories)
|
35
39
|
|
36
|
-
|
40
|
+
- if applicant_types.include?('Apply to Reclassify')
|
41
|
+
= f.show_if :applicant_type, 'Apply to Reclassify' do
|
42
|
+
= render('effective/applicants/select/apply_to_reclassify', f: f)
|
43
|
+
= render('effective/applicants/select/categories', f: f, categories: categories - [existing_category])
|
37
44
|
|
38
|
-
- if
|
39
|
-
= f.
|
40
|
-
=
|
45
|
+
- if applicant_types.include?('Apply for Reinstatement')
|
46
|
+
= f.show_if :applicant_type, 'Apply for Reinstatement' do
|
47
|
+
= f.hidden_field :category_id, value: existing_category.id
|
48
|
+
= render('effective/applicants/select/apply_for_reinstatement', f: f)
|
41
49
|
|
42
|
-
|
50
|
+
= f.save 'Save and Continue'
|
@@ -18,6 +18,7 @@ class CreateEffectiveMemberships < ActiveRecord::Migration[6.0]
|
|
18
18
|
|
19
19
|
t.text :applicant_wizard_steps
|
20
20
|
t.integer :applicant_fee
|
21
|
+
t.integer :applicant_reinstatement_fee
|
21
22
|
|
22
23
|
t.text :applicant_review_wizard_steps
|
23
24
|
|
@@ -458,6 +459,9 @@ class CreateEffectiveMemberships < ActiveRecord::Migration[6.0]
|
|
458
459
|
t.integer :category_id
|
459
460
|
t.string :category_type
|
460
461
|
|
462
|
+
t.integer :with_status_id
|
463
|
+
t.string :with_status_type
|
464
|
+
|
461
465
|
t.string :fee_type
|
462
466
|
|
463
467
|
t.integer :purchased_order_id
|
@@ -502,6 +506,9 @@ class CreateEffectiveMemberships < ActiveRecord::Migration[6.0]
|
|
502
506
|
t.integer :category_id
|
503
507
|
t.string :category_type
|
504
508
|
|
509
|
+
t.integer :with_status_id
|
510
|
+
t.string :with_status_type
|
511
|
+
|
505
512
|
t.date :period
|
506
513
|
|
507
514
|
# Acts as Statused
|
data/db/seeds.rb
CHANGED
@@ -9,6 +9,8 @@ if Rails.env.test?
|
|
9
9
|
Effective::ApplicantCourseName.delete_all
|
10
10
|
end
|
11
11
|
|
12
|
+
Effective::Status.where(title: 'Resigned').first_or_create!
|
13
|
+
|
12
14
|
member = Effective::Category.create!(
|
13
15
|
title: "Full Member",
|
14
16
|
can_apply_new: true,
|
@@ -18,6 +20,7 @@ member = Effective::Category.create!(
|
|
18
20
|
min_applicant_references: 2,
|
19
21
|
min_applicant_reviews: 2,
|
20
22
|
applicant_fee: 100_00,
|
23
|
+
applicant_reinstatement_fee: 50_00,
|
21
24
|
renewal_fee: 250_00,
|
22
25
|
late_fee: 50_00,
|
23
26
|
prorated_jan: 120_00, prorated_feb: 110_00, prorated_mar: 100_00, prorated_apr: 90_00, prorated_may: 80_00, prorated_jun: 70_00,
|
@@ -34,6 +37,7 @@ student = Effective::Category.create!(
|
|
34
37
|
min_applicant_references: 0,
|
35
38
|
min_applicant_reviews: 0,
|
36
39
|
applicant_fee: 50_00,
|
40
|
+
applicant_reinstatement_fee: 25_00,
|
37
41
|
renewal_fee: 125_00,
|
38
42
|
late_fee: 25_00,
|
39
43
|
prorated_jan: 120_00, prorated_feb: 110_00, prorated_mar: 100_00, prorated_apr: 90_00, prorated_may: 80_00, prorated_jun: 70_00,
|
@@ -49,6 +53,7 @@ retired = Effective::Category.create!(
|
|
49
53
|
can_apply_restricted: true,
|
50
54
|
can_apply_restricted_ids: [member.id],
|
51
55
|
applicant_fee: 0,
|
56
|
+
applicant_reinstatement_fee: 0,
|
52
57
|
renewal_fee: 0,
|
53
58
|
prorated_jan: 120_00, prorated_feb: 110_00, prorated_mar: 100_00, prorated_apr: 90_00, prorated_may: 80_00, prorated_jun: 70_00,
|
54
59
|
prorated_jul: 60_00, prorated_aug: 50_00, prorated_sep: 40_00, prorated_oct: 30_00, prorated_nov: 20_00, prorated_dec: 10_00,
|
@@ -66,6 +71,7 @@ member = Effective::Category.create!(
|
|
66
71
|
min_applicant_references: 2,
|
67
72
|
min_applicant_reviews: 2,
|
68
73
|
applicant_fee: 100_00,
|
74
|
+
applicant_reinstatement_fee: 50_00,
|
69
75
|
renewal_fee: 250_00,
|
70
76
|
late_fee: 50_00,
|
71
77
|
prorated_jan: 120_00, prorated_feb: 110_00, prorated_mar: 100_00, prorated_apr: 90_00, prorated_may: 80_00, prorated_jun: 70_00,
|
@@ -54,7 +54,7 @@ module EffectiveMemberships
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def self.fee_types
|
57
|
-
required = ['Applicant', 'Prorated', 'Discount', 'Renewal', 'Late', 'Admin']
|
57
|
+
required = ['Applicant', 'Reinstatement', 'Prorated', 'Discount', 'Renewal', 'Late', 'Admin']
|
58
58
|
additional = Array(additional_fee_types)
|
59
59
|
|
60
60
|
(required + additional).uniq.sort
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_memberships
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.3
|
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-08-
|
11
|
+
date: 2022-08-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -292,6 +292,7 @@ files:
|
|
292
292
|
- app/datatables/effective_applicant_courses_datatable.rb
|
293
293
|
- app/datatables/effective_applicant_educations_datatable.rb
|
294
294
|
- app/datatables/effective_applicant_endorsements_datatable.rb
|
295
|
+
- app/datatables/effective_applicant_endorsers_datatable.rb
|
295
296
|
- app/datatables/effective_applicant_equivalences_datatable.rb
|
296
297
|
- app/datatables/effective_applicant_experiences_datatable.rb
|
297
298
|
- app/datatables/effective_applicant_references_datatable.rb
|
@@ -391,6 +392,7 @@ files:
|
|
391
392
|
- app/views/effective/applicant_endorsements/_form_declaration.html.haml
|
392
393
|
- app/views/effective/applicant_endorsements/complete.html.haml
|
393
394
|
- app/views/effective/applicant_endorsements/edit.html.haml
|
395
|
+
- app/views/effective/applicant_endorsers/_dashboard.html.haml
|
394
396
|
- app/views/effective/applicant_references/_applicant_reference.html.haml
|
395
397
|
- app/views/effective/applicant_references/_datatable_actions.html.haml
|
396
398
|
- app/views/effective/applicant_references/_form.html.haml
|
@@ -413,6 +415,7 @@ files:
|
|
413
415
|
- app/views/effective/applicants/_orders.html.haml
|
414
416
|
- app/views/effective/applicants/_organization.html.haml
|
415
417
|
- app/views/effective/applicants/_references.html.haml
|
418
|
+
- app/views/effective/applicants/_reinstatement.html.haml
|
416
419
|
- app/views/effective/applicants/_select.html.haml
|
417
420
|
- app/views/effective/applicants/_select_organization.html.haml
|
418
421
|
- app/views/effective/applicants/_stamp.html.haml
|
@@ -431,7 +434,12 @@ files:
|
|
431
434
|
- app/views/effective/applicants/files.html.haml
|
432
435
|
- app/views/effective/applicants/organization.html.haml
|
433
436
|
- app/views/effective/applicants/references.html.haml
|
437
|
+
- app/views/effective/applicants/reinstatement.html.haml
|
434
438
|
- app/views/effective/applicants/select.html.haml
|
439
|
+
- app/views/effective/applicants/select/_apply_for_reinstatement.html.haml
|
440
|
+
- app/views/effective/applicants/select/_apply_to_join.html.haml
|
441
|
+
- app/views/effective/applicants/select/_apply_to_reclassify.html.haml
|
442
|
+
- app/views/effective/applicants/select/_categories.html.haml
|
435
443
|
- app/views/effective/applicants/stamp.html.haml
|
436
444
|
- app/views/effective/applicants/start.html.haml
|
437
445
|
- app/views/effective/applicants/submitted.html.haml
|