effective_memberships 0.4.7 → 0.4.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/effective_memberships/applicant_experiences.js +0 -5
- data/app/controllers/admin/applicant_endorsements_controller.rb +9 -0
- data/app/controllers/admin/memberships_controller.rb +1 -1
- data/app/controllers/effective/applicant_endorsements_controller.rb +48 -0
- data/app/controllers/effective/applicant_references_controller.rb +1 -1
- data/app/datatables/admin/effective_applicant_endorsements_datatable.rb +35 -0
- data/app/datatables/effective_applicant_endorsements_datatable.rb +37 -0
- data/app/datatables/effective_applicant_references_datatable.rb +1 -1
- data/app/mailers/effective/memberships_mailer.rb +25 -0
- data/app/models/concerns/effective_memberships_applicant.rb +34 -6
- data/app/models/concerns/effective_memberships_fee_payment.rb +0 -1
- data/app/models/concerns/effective_memberships_organization.rb +5 -0
- data/app/models/concerns/effective_memberships_owner.rb +18 -2
- data/app/models/concerns/effective_memberships_registrar.rb +31 -30
- data/app/models/concerns/effective_memberships_user.rb +5 -0
- data/app/models/effective/applicant_endorsement.rb +100 -0
- data/app/models/effective/membership.rb +40 -3
- data/app/models/effective/membership_history.rb +2 -0
- data/app/views/admin/applicant_endorsements/_applicant_endorsement.html.haml +1 -0
- data/app/views/admin/applicants/_form.html.haml +4 -0
- data/app/views/admin/categories/_form_applicant_steps.html.haml +6 -0
- data/app/views/admin/fee_payments/_fee_payment.html.haml +4 -0
- data/app/views/admin/fees/_form.html.haml +2 -3
- data/app/views/admin/memberships/_form_membership.html.haml +1 -1
- data/app/views/admin/users/_col.html.haml +12 -0
- data/app/views/effective/applicant_endorsements/_applicant_endorsement.html.haml +46 -0
- data/app/views/effective/applicant_endorsements/_datatable_actions.html.haml +4 -0
- data/app/views/effective/applicant_endorsements/_form.html.haml +9 -0
- data/app/views/effective/applicant_endorsements/_form_declaration.html.haml +22 -0
- data/app/views/effective/applicant_endorsements/complete.html.haml +3 -0
- data/app/views/effective/applicant_endorsements/edit.html.haml +8 -0
- data/app/views/effective/applicants/_endorsements.html.haml +15 -0
- data/app/views/effective/applicants/endorsements.html.haml +25 -0
- data/app/views/effective/applicants/experience.html.haml +1 -1
- data/app/views/effective/applicants/select.html.haml +6 -1
- data/app/views/effective/fee_payments/_orders.html.haml +1 -1
- data/app/views/effective/memberships_mailer/applicant_endorsement_notification.liquid +15 -0
- data/config/effective_memberships.rb +3 -0
- data/config/routes.rb +9 -0
- data/db/migrate/01_create_effective_memberships.rb.erb +30 -0
- data/lib/effective_memberships/version.rb +1 -1
- data/lib/effective_memberships.rb +1 -1
- metadata +32 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b7d09ef68f61058a8ee29567caa3a008d887482edab0fa3e8d251ea69f9ea3cb
|
4
|
+
data.tar.gz: 10a88e200464a6d2d7dbb8fbdcaa3aed77337b067e12fc3577b31a8032cbd2ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3adbdb1ab5f18df509ebc6631f39a142f2857213ce9ee0a23b83eec2fa44dda3d8b77c42afe7e4e4b494bb938dac7aee672cc26dacbd398fd9f34cc3c55ed222
|
7
|
+
data.tar.gz: ab80c7ff8b01736429ecabc774b81c45702d21ae521e2e7db276191802fa212171f8e81e448a06e452fb97745c5aec3723fe37537669f3a3ed87b9cd30d03746
|
@@ -31,8 +31,3 @@ $(document).on('change dp.change keyup', "[data-applicant-experiences-month]", f
|
|
31
31
|
const $form = $(event.currentTarget).closest('form');
|
32
32
|
sumApplicantExperiences($form);
|
33
33
|
});
|
34
|
-
|
35
|
-
|
36
|
-
// $(document).on 'cocoon:after-remove', (event) ->
|
37
|
-
// $form = $(event.target).closest('form')
|
38
|
-
// sumMonths($form) if $form.find('[data-experience-month]').length > 0
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Admin
|
2
|
+
class ApplicantEndorsementsController < ApplicationController
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
4
|
+
before_action { EffectiveResources.authorize!(self, :admin, :effective_memberships) }
|
5
|
+
|
6
|
+
include Effective::CrudController
|
7
|
+
|
8
|
+
end
|
9
|
+
end
|
@@ -5,7 +5,7 @@ module Admin
|
|
5
5
|
|
6
6
|
include Effective::CrudController
|
7
7
|
|
8
|
-
submit :
|
8
|
+
submit :revise, 'Update Membership',
|
9
9
|
success: -> { "#{resource.owner} has been successfully updated. Please double check the membership history is correct" },
|
10
10
|
redirect: -> { admin_owners_path(resource) }
|
11
11
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Effective
|
2
|
+
class ApplicantEndorsementsController < ApplicationController
|
3
|
+
include Effective::CrudController
|
4
|
+
include Effective::Select2AjaxController
|
5
|
+
|
6
|
+
page_title 'Confidential Endorsement Form'
|
7
|
+
|
8
|
+
# The show and update actions are public routes but can only be reached by the token.
|
9
|
+
# The endorser must declare and submit the form
|
10
|
+
# To move an applicant endorsement from submitted to completed
|
11
|
+
|
12
|
+
submit :notify, 'Resend email notification',
|
13
|
+
success: -> { "Sent email notification to #{resource.email}" }
|
14
|
+
|
15
|
+
submit :complete, 'Complete Endorsement'
|
16
|
+
|
17
|
+
def show
|
18
|
+
@applicant_endorsement = ApplicantEndorsement.submitted.find(params[:id])
|
19
|
+
EffectiveResources.authorize!(self, :show, @applicant_endorsement)
|
20
|
+
|
21
|
+
render 'edit'
|
22
|
+
end
|
23
|
+
|
24
|
+
# Must be signed in
|
25
|
+
def select2_ajax_endorser
|
26
|
+
authenticate_user! if defined?(Devise)
|
27
|
+
|
28
|
+
applicant = EffectiveMemberships.Applicant.find(params[:applicant_id])
|
29
|
+
collection = Effective::ApplicantEndorsement.endorser_collection(applicant)
|
30
|
+
|
31
|
+
respond_with_select2_ajax(collection)
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def permitted_params
|
37
|
+
permitted = params.require(:effective_applicant_endorsement).permit!.except(:token, :last_notified_at, :status, :status_steps, :applicant_id, :endorser_id)
|
38
|
+
|
39
|
+
if current_user && current_user.memberships_owners.include?(resource.applicant&.owner)
|
40
|
+
permitted.except(:notes, :accept_declaration)
|
41
|
+
else
|
42
|
+
permitted
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -23,7 +23,7 @@ module Effective
|
|
23
23
|
protected
|
24
24
|
|
25
25
|
def permitted_params
|
26
|
-
permitted = params.require(:effective_applicant_reference).permit!.except(:token, :last_notified_at, :status, :status_steps)
|
26
|
+
permitted = params.require(:effective_applicant_reference).permit!.except(:token, :last_notified_at, :status, :status_steps, :applicant_id)
|
27
27
|
|
28
28
|
if current_user && current_user.memberships_owners.include?(resource.applicant&.owner)
|
29
29
|
permitted.except(:reservations, :reservations_reason, :work_history, :accept_declaration)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Admin
|
2
|
+
class EffectiveApplicantEndorsementsDatatable < Effective::Datatable
|
3
|
+
|
4
|
+
datatable do
|
5
|
+
order :name
|
6
|
+
|
7
|
+
col :applicant
|
8
|
+
|
9
|
+
col :endorser
|
10
|
+
col :email
|
11
|
+
col :name
|
12
|
+
col :phone
|
13
|
+
col :unknown_member, visible: false
|
14
|
+
|
15
|
+
col :status do |endorsement|
|
16
|
+
if endorsement.submitted?
|
17
|
+
'Waiting on response'
|
18
|
+
elsif endorsement.completed?
|
19
|
+
'Completed'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
col :last_notified_at do |endorsement|
|
24
|
+
endorsement.last_notified_at&.strftime('%F') unless endorsement.completed?
|
25
|
+
end
|
26
|
+
|
27
|
+
actions_col
|
28
|
+
end
|
29
|
+
|
30
|
+
collection do
|
31
|
+
Effective::ApplicantEndorsement.deep.all
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# For the applicant complete step to add additional endorsements
|
2
|
+
class EffectiveApplicantEndorsementsDatatable < Effective::Datatable
|
3
|
+
|
4
|
+
datatable do
|
5
|
+
order :name
|
6
|
+
|
7
|
+
col :name do |endorsement|
|
8
|
+
endorser&.to_s || name
|
9
|
+
end
|
10
|
+
|
11
|
+
col :email
|
12
|
+
col :phone
|
13
|
+
|
14
|
+
col :status do |reference|
|
15
|
+
if reference.submitted?
|
16
|
+
'Waiting on response'
|
17
|
+
elsif reference.completed?
|
18
|
+
'Completed'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
col :last_notified_at do |endorsement|
|
23
|
+
endorsement.last_notified_at&.strftime('%F') unless endorsement.completed?
|
24
|
+
end
|
25
|
+
|
26
|
+
actions_col partial: 'effective/applicant_endorsements/datatable_actions', partial_as: :applicant_endorsement
|
27
|
+
end
|
28
|
+
|
29
|
+
collection do
|
30
|
+
Effective::ApplicantEndorsement.deep.where(applicant: applicant)
|
31
|
+
end
|
32
|
+
|
33
|
+
def applicant
|
34
|
+
@applicant ||= EffectiveMemberships.Applicant.where(id: attributes[:applicant_id]).first!
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -44,6 +44,16 @@ module Effective
|
|
44
44
|
mail(to: resource.user.email, subject: subject, **headers)
|
45
45
|
end
|
46
46
|
|
47
|
+
def applicant_endorsement_notification(resource, opts = {})
|
48
|
+
@assigns = assigns_for(resource)
|
49
|
+
@applicant_endorsement = resource
|
50
|
+
|
51
|
+
subject = subject_for(__method__, 'Endorsement Requested', resource, opts)
|
52
|
+
headers = headers_for(resource, opts)
|
53
|
+
|
54
|
+
mail(to: resource.email, subject: subject, **headers)
|
55
|
+
end
|
56
|
+
|
47
57
|
def applicant_reference_notification(resource, opts = {})
|
48
58
|
@assigns = assigns_for(resource)
|
49
59
|
@applicant_reference = resource
|
@@ -61,6 +71,10 @@ module Effective
|
|
61
71
|
return applicant_assigns(resource).merge(owner_assigns(resource.owner))
|
62
72
|
end
|
63
73
|
|
74
|
+
if resource.kind_of?(Effective::ApplicantEndorsement)
|
75
|
+
return endorsement_assigns(resource).merge(owner_assigns(resource.applicant.owner))
|
76
|
+
end
|
77
|
+
|
64
78
|
if resource.kind_of?(Effective::ApplicantReference)
|
65
79
|
return reference_assigns(resource).merge(owner_assigns(resource.applicant.owner))
|
66
80
|
end
|
@@ -88,6 +102,17 @@ module Effective
|
|
88
102
|
{ applicant: values }
|
89
103
|
end
|
90
104
|
|
105
|
+
def endorsement_assigns(applicant_endorsement)
|
106
|
+
raise('expected a endorsement') unless applicant_endorsement.kind_of?(Effective::ApplicantEndorsement)
|
107
|
+
|
108
|
+
values = {
|
109
|
+
name: (applicant_endorsement.endorser&.to_s || applicant_endorsement.name),
|
110
|
+
url: effective_memberships.applicant_endorsement_url(applicant_endorsement)
|
111
|
+
}
|
112
|
+
|
113
|
+
{ endorsement: values }
|
114
|
+
end
|
115
|
+
|
91
116
|
def reference_assigns(applicant_reference)
|
92
117
|
raise('expected a reference') unless applicant_reference.kind_of?(Effective::ApplicantReference)
|
93
118
|
|
@@ -93,6 +93,9 @@ module EffectiveMembershipsApplicant
|
|
93
93
|
has_many :applicant_educations, -> { order(:id) }, class_name: 'Effective::ApplicantEducation', as: :applicant, inverse_of: :applicant, dependent: :destroy
|
94
94
|
accepts_nested_attributes_for :applicant_educations, reject_if: :all_blank, allow_destroy: true
|
95
95
|
|
96
|
+
has_many :applicant_endorsements, -> { order(:id) }, class_name: 'Effective::ApplicantEndorsement', as: :applicant, inverse_of: :applicant, dependent: :destroy
|
97
|
+
accepts_nested_attributes_for :applicant_endorsements, reject_if: :all_blank, allow_destroy: true
|
98
|
+
|
96
99
|
has_many :applicant_experiences, -> { order(:id) }, class_name: 'Effective::ApplicantExperience', as: :applicant, inverse_of: :applicant, dependent: :destroy
|
97
100
|
accepts_nested_attributes_for :applicant_experiences, reject_if: :all_blank, allow_destroy: true
|
98
101
|
|
@@ -238,6 +241,16 @@ module EffectiveMembershipsApplicant
|
|
238
241
|
end
|
239
242
|
end
|
240
243
|
|
244
|
+
# Applicant Endorsements Step
|
245
|
+
with_options(if: -> { current_step == :endorsements }) do
|
246
|
+
validate do
|
247
|
+
required = min_applicant_endorsements()
|
248
|
+
existing = applicant_endorsements().reject(&:marked_for_destruction?).length
|
249
|
+
|
250
|
+
self.errors.add(:applicant_endorsements, "please include #{required} or more endorsements") if existing < required
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
241
254
|
# Applicant References Step
|
242
255
|
with_options(if: -> { current_step == :references }) do
|
243
256
|
validate do
|
@@ -361,6 +374,7 @@ module EffectiveMembershipsApplicant
|
|
361
374
|
stamps.each { |stamp| stamp.submit! }
|
362
375
|
|
363
376
|
after_commit do
|
377
|
+
applicant_endorsements.each { |endorsement| endorsement.notify! if endorsement.submitted? }
|
364
378
|
applicant_references.each { |reference| reference.notify! if reference.submitted? }
|
365
379
|
end
|
366
380
|
|
@@ -521,6 +535,11 @@ module EffectiveMembershipsApplicant
|
|
521
535
|
category&.min_applicant_references.to_i
|
522
536
|
end
|
523
537
|
|
538
|
+
# Endorsements Step
|
539
|
+
def min_applicant_endorsements
|
540
|
+
category&.min_applicant_endorsements.to_i
|
541
|
+
end
|
542
|
+
|
524
543
|
# Files Step
|
525
544
|
def min_applicant_files
|
526
545
|
category&.min_applicant_files.to_i
|
@@ -536,6 +555,10 @@ module EffectiveMembershipsApplicant
|
|
536
555
|
)
|
537
556
|
end
|
538
557
|
|
558
|
+
def applicant_endorsements_required?
|
559
|
+
min_applicant_endorsements > 0
|
560
|
+
end
|
561
|
+
|
539
562
|
def applicant_references_required?
|
540
563
|
min_applicant_references > 0
|
541
564
|
end
|
@@ -543,13 +566,18 @@ module EffectiveMembershipsApplicant
|
|
543
566
|
# When an application is submitted, these must be done to go to completed.
|
544
567
|
# An Admin can override this and just set them to completed.
|
545
568
|
def completed_requirements
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
{}
|
569
|
+
requirements = {}
|
570
|
+
return requirements unless category.present?
|
571
|
+
|
572
|
+
if category.applicant_wizard_steps.include?(:references) || applicant_references_required?
|
573
|
+
requirements['Applicant References'] = (!applicant_references_required? || applicant_references.count(&:completed?) >= min_applicant_references)
|
552
574
|
end
|
575
|
+
|
576
|
+
if category.applicant_wizard_steps.include?(:endorsements) || applicant_endorsements_required?
|
577
|
+
requirements['Applicant Endorsements'] = (!applicant_endorsements_required? || applicant_endorsements.count(&:completed?) >= min_applicant_endorsements)
|
578
|
+
end
|
579
|
+
|
580
|
+
requirements
|
553
581
|
end
|
554
582
|
|
555
583
|
def complete!
|
@@ -62,6 +62,11 @@ module EffectiveMembershipsOrganization
|
|
62
62
|
scope :deep, -> { includes(:representatives) }
|
63
63
|
scope :sorted, -> { order(:title) }
|
64
64
|
|
65
|
+
scope :membership_applying, -> {
|
66
|
+
applicants = EffectiveMemberships.Applicant.all
|
67
|
+
without_role(:member).where(id: applicants.select(:organization_id))
|
68
|
+
}
|
69
|
+
|
65
70
|
validates :title, presence: true, uniqueness: true
|
66
71
|
validates :email, presence: true
|
67
72
|
end
|
@@ -37,6 +37,22 @@ module EffectiveMembershipsOwner
|
|
37
37
|
accepts_nested_attributes_for :membership_histories
|
38
38
|
|
39
39
|
scope :members, -> { joins(:membership) }
|
40
|
+
|
41
|
+
scope :membership_removed, -> {
|
42
|
+
removed = Effective::MembershipHistory.removed.where(owner_type: name)
|
43
|
+
without_role(:member).where(id: removed.select(:owner_id))
|
44
|
+
}
|
45
|
+
|
46
|
+
scope :membership_bad_standing, -> {
|
47
|
+
bad_standing = Effective::Membership.where(bad_standing: true).where(owner_type: name)
|
48
|
+
where(id: bad_standing.select(:owner_id))
|
49
|
+
}
|
50
|
+
|
51
|
+
scope :membership_renewed_this_period, -> {
|
52
|
+
with_paid_fees_through = Effective::Membership.with_paid_fees_through.where(owner_type: name)
|
53
|
+
where(id: with_paid_fees_through.select(:owner_id))
|
54
|
+
}
|
55
|
+
|
40
56
|
end
|
41
57
|
|
42
58
|
def assign_member_role
|
@@ -181,8 +197,8 @@ module EffectiveMembershipsOwner
|
|
181
197
|
# Build the renewal fee
|
182
198
|
fee ||= fees.build()
|
183
199
|
|
184
|
-
late_on ||= EffectiveMemberships.Registrar.late_fee_date(period: period)
|
185
|
-
bad_standing_on ||= EffectiveMemberships.Registrar.bad_standing_date(period: period)
|
200
|
+
late_on ||= EffectiveMemberships.Registrar.late_fee_date(period: period) if category.create_late_fees?
|
201
|
+
bad_standing_on ||= EffectiveMemberships.Registrar.bad_standing_date(period: period) if category.create_bad_standing?
|
186
202
|
|
187
203
|
fee.assign_attributes(
|
188
204
|
fee_type: 'Renewal',
|
@@ -284,52 +284,53 @@ module EffectiveMembershipsRegistrar
|
|
284
284
|
retval
|
285
285
|
end
|
286
286
|
|
287
|
-
|
288
287
|
# This is intended to be run once per day in a rake task
|
289
288
|
# rake effective_memberships:create_fees
|
290
289
|
# Create Renewal and Late fees
|
291
|
-
def create_fees!(period: nil
|
292
|
-
# The current period, based on Time.zone.now
|
290
|
+
def create_fees!(period: nil)
|
293
291
|
period ||= current_period
|
294
|
-
|
295
|
-
bad_standing_on ||= bad_standing_date(period: period)
|
292
|
+
memberships = Effective::Membership.deep.with_unpaid_fees_through(period)
|
296
293
|
|
297
294
|
# Create Renewal Fees
|
298
|
-
|
299
|
-
|
300
|
-
existing = membership.owner.membership_period_fee(category: category, period: period, except: 'Renewal')
|
301
|
-
next if existing.present? # This might be an existing Prorated fee
|
295
|
+
memberships.find_each { |membership| create_renewal_fees!(membership, period: period) }
|
296
|
+
GC.start
|
302
297
|
|
303
|
-
|
304
|
-
|
305
|
-
|
298
|
+
# Create Late Fees
|
299
|
+
memberships.find_each { |membership| create_late_fees!(membership, period: period) }
|
300
|
+
GC.start
|
306
301
|
|
307
|
-
|
302
|
+
# Update Membership Status - Assign In Bad Standing
|
303
|
+
memberships.find_each { |membership| update_membership_status!(membership, period: period) }
|
304
|
+
GC.start
|
308
305
|
|
309
|
-
|
310
|
-
|
311
|
-
end
|
306
|
+
true
|
307
|
+
end
|
312
308
|
|
313
|
-
|
309
|
+
def create_renewal_fees!(membership, period:)
|
310
|
+
membership.categories.select(&:create_renewal_fees?).map do |category|
|
311
|
+
existing = membership.owner.membership_period_fee(category: category, period: period, except: 'Renewal')
|
312
|
+
next if existing.present? # This might be an existing Prorated fee
|
314
313
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
fee = membership.owner.build_late_fee(category: category, period: period)
|
319
|
-
next if fee.blank? || fee.purchased?
|
314
|
+
fee = membership.owner.build_renewal_fee(category: category, period: period)
|
315
|
+
raise("expected build_renewal_fee to return a fee for period #{period}") unless fee.kind_of?(Effective::Fee)
|
316
|
+
next if fee.purchased?
|
320
317
|
|
321
|
-
|
322
|
-
end
|
323
|
-
end
|
318
|
+
puts("Created renewal fee for #{membership.owner}") if fee.new_record? && !Rails.env.test?
|
324
319
|
|
325
|
-
|
320
|
+
fee.save!
|
321
|
+
end
|
322
|
+
end
|
326
323
|
|
327
|
-
|
328
|
-
|
329
|
-
membership.owner.
|
324
|
+
def create_late_fees!(membership, period:)
|
325
|
+
membership.categories.select(&:create_late_fees?).map do |category|
|
326
|
+
fee = membership.owner.build_late_fee(category: category, period: period)
|
327
|
+
next if fee.blank? || fee.purchased?
|
328
|
+
fee.save!
|
330
329
|
end
|
330
|
+
end
|
331
331
|
|
332
|
-
|
332
|
+
def update_membership_status!(membership, period: nil)
|
333
|
+
membership.owner.update_membership_status!
|
333
334
|
end
|
334
335
|
|
335
336
|
# Called in the after_purchase of fee payment
|
@@ -27,6 +27,11 @@ module EffectiveMembershipsUser
|
|
27
27
|
class_name: 'Effective::Representative', inverse_of: :user, dependent: :delete_all
|
28
28
|
|
29
29
|
accepts_nested_attributes_for :representatives, allow_destroy: true
|
30
|
+
|
31
|
+
scope :membership_applying, -> {
|
32
|
+
applicants = EffectiveMemberships.Applicant.all
|
33
|
+
without_role(:member).where(id: applicants.select(:user_id))
|
34
|
+
}
|
30
35
|
end
|
31
36
|
|
32
37
|
# Instance Methods
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# An ApplicantEndorsement is similar to a reference, except it must be an existing member
|
2
|
+
|
3
|
+
module Effective
|
4
|
+
class ApplicantEndorsement < ActiveRecord::Base
|
5
|
+
acts_as_tokened
|
6
|
+
|
7
|
+
acts_as_statused(
|
8
|
+
:submitted, # Was submitted by the applicant
|
9
|
+
:completed # Was completed by the endorser.
|
10
|
+
)
|
11
|
+
|
12
|
+
log_changes(to: :applicant) if respond_to?(:log_changes)
|
13
|
+
|
14
|
+
belongs_to :applicant, polymorphic: true
|
15
|
+
belongs_to :endorser, polymorphic: true, optional: true
|
16
|
+
|
17
|
+
effective_resource do
|
18
|
+
# These fields are submitted by the applicant
|
19
|
+
# They should try to select an endorser from the dropdown
|
20
|
+
# But we also allow a fallback
|
21
|
+
unknown_member :boolean
|
22
|
+
endorser_email :string
|
23
|
+
name :string
|
24
|
+
phone :string
|
25
|
+
|
26
|
+
# As per acts_as_statused. For tracking the state machine.
|
27
|
+
status :string
|
28
|
+
status_steps :text
|
29
|
+
|
30
|
+
# Endorser Declaration
|
31
|
+
notes :text
|
32
|
+
accept_declaration :boolean
|
33
|
+
|
34
|
+
# Tracking the submission
|
35
|
+
token :string
|
36
|
+
last_notified_at :datetime
|
37
|
+
|
38
|
+
timestamps
|
39
|
+
end
|
40
|
+
|
41
|
+
scope :deep, -> { all }
|
42
|
+
|
43
|
+
# All step validations
|
44
|
+
validates :applicant, presence: true
|
45
|
+
validates :endorser, presence: true, unless: -> { unknown_member? }
|
46
|
+
|
47
|
+
with_options(if: -> { unknown_member? }) do
|
48
|
+
validates :endorser_email, presence: true, email: true
|
49
|
+
validates :name, presence: true
|
50
|
+
validates :phone, presence: true
|
51
|
+
end
|
52
|
+
|
53
|
+
# When being submit by the reference
|
54
|
+
with_options(if: -> { completed? }) do
|
55
|
+
validates :accept_declaration, acceptance: true
|
56
|
+
end
|
57
|
+
|
58
|
+
after_commit(on: :create, if: -> { applicant.was_submitted? }) { notify! }
|
59
|
+
|
60
|
+
def self.endorser_collection(applicant)
|
61
|
+
raise('expected an effective memberships applicant') unless applicant.class.try(:effective_memberships_applicant?)
|
62
|
+
|
63
|
+
collection_method = EffectiveMemberships.applicant_endorsements_endorser_collection()
|
64
|
+
|
65
|
+
if collection_method.blank?
|
66
|
+
return (applicant.user.class.members)
|
67
|
+
end
|
68
|
+
|
69
|
+
collection = instance_exec(applicant, &collection_method)
|
70
|
+
|
71
|
+
unless collection.kind_of?(ActiveRecord::Relation)
|
72
|
+
raise("expected EffectiveMemberships.applicant_endorsements_endorsers_collection to return an ActiveRecord::Relation.")
|
73
|
+
end
|
74
|
+
|
75
|
+
collection
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_s
|
79
|
+
'endorsement'
|
80
|
+
end
|
81
|
+
|
82
|
+
def email
|
83
|
+
endorser&.email || endorser_email
|
84
|
+
end
|
85
|
+
|
86
|
+
def notify!
|
87
|
+
raise('expected endorsement email') unless email.present?
|
88
|
+
|
89
|
+
EffectiveMemberships.send_email(:applicant_endorsement_notification, self)
|
90
|
+
update!(last_notified_at: Time.zone.now)
|
91
|
+
end
|
92
|
+
|
93
|
+
def complete!
|
94
|
+
completed!
|
95
|
+
applicant.save!
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -38,8 +38,9 @@ module Effective
|
|
38
38
|
}
|
39
39
|
|
40
40
|
scope :with_unpaid_fees_through, -> (period = nil) {
|
41
|
-
where(arel_table[:
|
42
|
-
.or(where(fees_paid_period: nil))
|
41
|
+
joined = where(arel_table[:joined_on].lt(period || EffectiveMemberships.Registrar.current_period))
|
42
|
+
unpaid = where(arel_table[:fees_paid_period].lt(period || EffectiveMemberships.Registrar.current_period)).or(where(fees_paid_period: nil))
|
43
|
+
joined.merge(unpaid)
|
43
44
|
}
|
44
45
|
|
45
46
|
before_validation do
|
@@ -119,7 +120,24 @@ module Effective
|
|
119
120
|
end
|
120
121
|
|
121
122
|
def fees_paid?
|
122
|
-
|
123
|
+
paid_fees_through?(EffectiveMemberships.Registrar.current_period)
|
124
|
+
end
|
125
|
+
|
126
|
+
def paid_fees_through?(period = nil)
|
127
|
+
period ||= EffectiveMemberships.Registrar.current_period
|
128
|
+
|
129
|
+
return false if fees_paid_period.blank?
|
130
|
+
fees_paid_period >= period
|
131
|
+
end
|
132
|
+
|
133
|
+
def unpaid_fees_through?(period = nil)
|
134
|
+
period ||= EffectiveMemberships.Registrar.current_period
|
135
|
+
|
136
|
+
return false if joined_on.blank?
|
137
|
+
return false unless joined_on < period
|
138
|
+
|
139
|
+
return true if fees_paid_period.blank?
|
140
|
+
fees_paid_period < period
|
123
141
|
end
|
124
142
|
|
125
143
|
def change_fees_paid_period
|
@@ -127,6 +145,10 @@ module Effective
|
|
127
145
|
end
|
128
146
|
|
129
147
|
def change_fees_paid_period=(date)
|
148
|
+
if date.blank?
|
149
|
+
return assign_attributes(fees_paid_period: nil, fees_paid_through_period: nil)
|
150
|
+
end
|
151
|
+
|
130
152
|
date = (date.respond_to?(:strftime) ? date : Date.parse(date))
|
131
153
|
|
132
154
|
period = EffectiveMemberships.Registrar.period(date: date)
|
@@ -135,5 +157,20 @@ module Effective
|
|
135
157
|
assign_attributes(fees_paid_period: period, fees_paid_through_period: period_end_on)
|
136
158
|
end
|
137
159
|
|
160
|
+
# Admin updating membership info
|
161
|
+
def revise!
|
162
|
+
save!
|
163
|
+
|
164
|
+
period = EffectiveMemberships.Registrar.current_period
|
165
|
+
return true if paid_fees_through?(period)
|
166
|
+
|
167
|
+
# Otherwise build fees right now
|
168
|
+
EffectiveMemberships.Registrar.create_renewal_fees!(self, period: period)
|
169
|
+
EffectiveMemberships.Registrar.create_late_fees!(self, period: period)
|
170
|
+
EffectiveMemberships.Registrar.update_membership_status!(self, period: period)
|
171
|
+
|
172
|
+
true
|
173
|
+
end
|
174
|
+
|
138
175
|
end
|
139
176
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
= render '/effective/applicant_endorsements/applicant_endorsement', applicant_endorsement: applicant_endorsement, skip_actions: true
|
@@ -25,6 +25,10 @@
|
|
25
25
|
= tab 'References' do
|
26
26
|
.mb-4= render_inline_datatable(Admin::EffectiveApplicantReferencesDatatable.new(applicant: applicant))
|
27
27
|
|
28
|
+
- if applicant.applicant_endorsements.present?
|
29
|
+
= tab 'Endorsements' do
|
30
|
+
.mb-4= render_inline_datatable(Admin::EffectiveApplicantEndorsementsDatatable.new(applicant: applicant))
|
31
|
+
|
28
32
|
- if applicant.fees.present? || applicant.orders.present?
|
29
33
|
= tab 'Fees' do
|
30
34
|
.mb-4
|
@@ -32,6 +32,12 @@
|
|
32
32
|
%td= f.number_field :min_applicant_experiences_months, label: false
|
33
33
|
%td minimimum months of work experience
|
34
34
|
|
35
|
+
- if applicant.wizard_step_keys.include?(:endorsements)
|
36
|
+
%tr
|
37
|
+
%td= applicant.wizard_step_title(:endorsements)
|
38
|
+
%td= f.number_field :min_applicant_endorsements, label: false
|
39
|
+
%td minimimum number of endorsements
|
40
|
+
|
35
41
|
- if applicant.wizard_step_keys.include?(:references)
|
36
42
|
%tr
|
37
43
|
%td= applicant.wizard_step_title(:references)
|
@@ -3,9 +3,8 @@
|
|
3
3
|
= f.hidden_field :owner_id
|
4
4
|
= f.hidden_field :owner_type
|
5
5
|
- else
|
6
|
-
-
|
7
|
-
|
8
|
-
= f.select :owner_id, collection, polymorphic: true
|
6
|
+
- collection = { 'Users' => current_user.class.sorted, 'Organizations' => EffectiveMemberships.Organization.sorted }
|
7
|
+
= f.select :owner, collection, polymorphic: true
|
9
8
|
|
10
9
|
- if f.object.new_record?
|
11
10
|
= f.select :fee_type, EffectiveMemberships.custom_fee_types
|
@@ -21,7 +21,7 @@
|
|
21
21
|
- periods = registrar.periods(from: f.object.joined_on)
|
22
22
|
- collection = periods.reverse.map { |period| [registrar.period_end_on(date: period), period] }
|
23
23
|
|
24
|
-
= f.select :change_fees_paid_period, collection, label: 'Fees Paid Through', hint: 'Which period this user has fees paid through.
|
24
|
+
= f.select :change_fees_paid_period, collection, label: 'Fees Paid Through', hint: 'Which period this user has fees paid through. Determines which renewal fees should be created. Setting this to a past or blank period may create a renewal fee in the current period.'
|
25
25
|
|
26
26
|
%p.text-muted To update the current membership categories, use the 'Assign' or 'Reclassify' actions below
|
27
27
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
- user = (resource.respond_to?(:email) ? resource : resource.user)
|
2
|
+
|
3
|
+
= user.to_s
|
4
|
+
|
5
|
+
- if user.email.present?
|
6
|
+
%br
|
7
|
+
= mail_to user.email
|
8
|
+
|
9
|
+
- if user.membership.present?
|
10
|
+
%br
|
11
|
+
= '#' + user.membership.number
|
12
|
+
#{user.membership.categories.to_sentence}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
- endorsement = applicant_endorsement
|
2
|
+
|
3
|
+
%table.table.table-sm
|
4
|
+
%tbody
|
5
|
+
%tr
|
6
|
+
%th Endorser
|
7
|
+
%td
|
8
|
+
- if endorsement.endorser.present?
|
9
|
+
- endorser = endorsement.endorser
|
10
|
+
= link_to("#{endorser.to_s} <#{endorser.email}>", "mailto:#{endorser.email}")
|
11
|
+
- else
|
12
|
+
= link_to("#{endorsement.name} <#{endorsement.email}>", "mailto:#{endorsement.email}")
|
13
|
+
%td
|
14
|
+
|
15
|
+
- if endorsement.phone.present?
|
16
|
+
%tr
|
17
|
+
%th Phone
|
18
|
+
%td= endorsement.phone
|
19
|
+
|
20
|
+
- if endorsement.applicant.was_submitted?
|
21
|
+
%tr
|
22
|
+
%th Status
|
23
|
+
%td
|
24
|
+
- if endorsement.submitted?
|
25
|
+
Waiting on response
|
26
|
+
- elsif endorsement.completed?
|
27
|
+
Response completed
|
28
|
+
|
29
|
+
- unless endorsement.applicant.was_approved?
|
30
|
+
%tr
|
31
|
+
%th Last Notified at
|
32
|
+
%td= endorsement.last_notified_at&.strftime('%F') || 'Never'
|
33
|
+
|
34
|
+
- if can?(:notify, endorsement) && !local_assigns[:skip_actions]
|
35
|
+
%tr
|
36
|
+
%th Notification
|
37
|
+
%td= link_to('Resend email notification', effective_memberships.notify_applicant_endorsement_path(endorsement), 'data-method': :post, 'data-confirm': "Really resend email notification to #{endorsement.email}?")
|
38
|
+
|
39
|
+
- if endorsement.completed? && can?(:review, endorsement)
|
40
|
+
%tr
|
41
|
+
%th Notes
|
42
|
+
%td= endorsement.notes
|
43
|
+
|
44
|
+
%tr
|
45
|
+
%th Endorsed On
|
46
|
+
%td= endorsement.completed_at.strftime('%F')
|
@@ -0,0 +1,4 @@
|
|
1
|
+
= dropdown(variation: :dropleft) do
|
2
|
+
- unless applicant_endorsement.completed?
|
3
|
+
= dropdown_link_to 'Notify', effective_memberships.notify_applicant_endorsement_path(applicant_endorsement),
|
4
|
+
data: { method: :post, confirm: "Really notify #{applicant_endorsement.email}?" }
|
@@ -0,0 +1,9 @@
|
|
1
|
+
= effective_form_with(model: applicant_endorsement, engine: true) do |f|
|
2
|
+
= f.hidden_field :applicant_id
|
3
|
+
= f.hidden_field :applicant_type
|
4
|
+
|
5
|
+
- if f.object.new_record?
|
6
|
+
%p An email will be sent asking them to complete a endorsement declaration form.
|
7
|
+
= f.submit('Create and Notify endorser')
|
8
|
+
- else
|
9
|
+
= f.submit
|
@@ -0,0 +1,22 @@
|
|
1
|
+
= effective_form_with(model: applicant_endorsement, engine: true) do |f|
|
2
|
+
%h2 Applicant endorsement
|
3
|
+
|
4
|
+
%p
|
5
|
+
I endorse and sponser
|
6
|
+
= applicant_endorsement.applicant.owner
|
7
|
+
as a candidate for
|
8
|
+
= applicant_endorsement.applicant.category
|
9
|
+
membership and certify that I have personal knowledge of the professional ability
|
10
|
+
and character, methods of practice, and experience of the applicant.
|
11
|
+
|
12
|
+
%p
|
13
|
+
The candidate has satisfied the requirements for membership in this category,
|
14
|
+
and to the best of my personal knowledge,
|
15
|
+
the applicant observes and upholds the Code of Ethics and Professional Practice.
|
16
|
+
|
17
|
+
.mt-4
|
18
|
+
|
19
|
+
= f.text_area :notes, label: "Additional comments"
|
20
|
+
= f.check_box :accept_declaration, label: 'Yes, I declare that the above information is true and accurate'
|
21
|
+
|
22
|
+
= f.submit 'Complete Endorsement'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
.card
|
2
|
+
.card-body
|
3
|
+
.row
|
4
|
+
.col-sm
|
5
|
+
%h5.card-title= applicant.wizard_step_title(:endorsements)
|
6
|
+
.col-sm-auto.text-right
|
7
|
+
= link_to('Edit', wizard_path(:endorsements)) if edit_effective_wizard?
|
8
|
+
|
9
|
+
- applicant.applicant_endorsements.each_with_index do |applicant_endorsement, index|
|
10
|
+
- if index > 0
|
11
|
+
.mb-4
|
12
|
+
|
13
|
+
%h6 Endorsement ##{index + 1}
|
14
|
+
|
15
|
+
= render('effective/applicant_endorsements/applicant_endorsement', applicant_endorsement: applicant_endorsement)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
= render 'layout' do
|
2
|
+
= render 'effective/applicants/content', resource: resource
|
3
|
+
|
4
|
+
.card
|
5
|
+
.card-body
|
6
|
+
- if resource.min_applicant_endorsements > 0
|
7
|
+
%p You must include #{resource.min_applicant_endorsements} or more endorsements.
|
8
|
+
|
9
|
+
= effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
|
10
|
+
= f.hidden_field :id
|
11
|
+
|
12
|
+
= f.has_many(:applicant_endorsements, cards: true) do |aef|
|
13
|
+
%h4 Endorsement
|
14
|
+
|
15
|
+
= aef.select :endorser, Effective::ApplicantEndorsement.endorser_collection(resource), required: false,
|
16
|
+
ajax_url: effective_memberships.select2_ajax_endorser_applicant_endorsement_path(applicant_id: resource)
|
17
|
+
|
18
|
+
= aef.check_box :unknown_member, label: 'I cant find my endorser in the above list'
|
19
|
+
|
20
|
+
= aef.show_if(:unknown_member, true) do
|
21
|
+
= aef.email_field :endorser_email, required: true
|
22
|
+
= aef.text_field :name, required: true
|
23
|
+
= aef.phone_field :phone, required: true
|
24
|
+
|
25
|
+
= f.save 'Save and Continue'
|
@@ -27,9 +27,14 @@
|
|
27
27
|
= f.show_if(:category_id, mc.id) do
|
28
28
|
.mb-4
|
29
29
|
%h3= mc.to_s
|
30
|
-
|
30
|
+
|
31
|
+
- if organization_categories.present?
|
32
|
+
%small.text-muted #{mc.category} #{mc.category_type} Membership
|
33
|
+
|
31
34
|
= mc.rich_text_body
|
32
35
|
|
36
|
+
= render_if_exists("effective/applicants/select/#{mc.to_s.parameterize.underscore}", f: f, category: mc)
|
37
|
+
|
33
38
|
- if organization_categories.present?
|
34
39
|
= f.show_if_any(:category_id, organization_categories.map(&:id)) do
|
35
40
|
= render('effective/applicants/select_organization', f: f)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
subject: 'Your endorsement has been requested'
|
3
|
+
from: 'admin@example.com'
|
4
|
+
---
|
5
|
+
Hello {{ endorsement.name }},
|
6
|
+
|
7
|
+
An applicant, {{ user.name }}, has requested your endorsement.
|
8
|
+
|
9
|
+
Would you please complete the endorsement declaration form at this url:
|
10
|
+
|
11
|
+
{{ endorsement.url }}
|
12
|
+
|
13
|
+
Thank you.
|
14
|
+
|
15
|
+
Please contact us for assistance.
|
@@ -24,6 +24,9 @@ EffectiveMemberships.setup do |config|
|
|
24
24
|
# The defaults include: Applicant, Prorated, Renewal, Late, Admin
|
25
25
|
# config.additional_fee_types = []
|
26
26
|
|
27
|
+
# Applicant Endorsements
|
28
|
+
# config.applicant_endorsements_endorser_collection = Proc.new { |applicant| applicant.user.class.members }
|
29
|
+
|
27
30
|
# Applicant Reviews
|
28
31
|
# When true, display the reviewed state and require Category.min_applicant_reviews
|
29
32
|
# When false, hide the reviewed state entirely
|
data/config/routes.rb
CHANGED
@@ -9,6 +9,11 @@ EffectiveMemberships::Engine.routes.draw do
|
|
9
9
|
resources :build, controller: :applicants, only: [:show, :update]
|
10
10
|
end
|
11
11
|
|
12
|
+
resources :applicant_endorsements, only: [:new, :create, :show, :update] do
|
13
|
+
get :select2_ajax_endorser, on: :member
|
14
|
+
post :notify, on: :member
|
15
|
+
end
|
16
|
+
|
12
17
|
resources :applicant_references, only: [:new, :create, :show, :update] do
|
13
18
|
post :notify, on: :member
|
14
19
|
end
|
@@ -32,6 +37,10 @@ EffectiveMemberships::Engine.routes.draw do
|
|
32
37
|
namespace :admin do
|
33
38
|
resources :applicants, except: [:new, :create, :show]
|
34
39
|
|
40
|
+
resources :applicant_endorsements do
|
41
|
+
post :notify, on: :member
|
42
|
+
end
|
43
|
+
|
35
44
|
resources :applicant_references do
|
36
45
|
post :notify, on: :member
|
37
46
|
end
|
@@ -24,6 +24,7 @@ class CreateEffectiveMemberships < ActiveRecord::Migration[6.0]
|
|
24
24
|
t.integer :min_applicant_educations
|
25
25
|
t.integer :min_applicant_experiences_months
|
26
26
|
t.integer :min_applicant_references
|
27
|
+
t.integer :min_applicant_endorsements
|
27
28
|
t.integer :min_applicant_courses
|
28
29
|
t.integer :min_applicant_files
|
29
30
|
|
@@ -295,6 +296,35 @@ class CreateEffectiveMemberships < ActiveRecord::Migration[6.0]
|
|
295
296
|
add_index :applicant_references, :applicant_id
|
296
297
|
add_index :applicant_references, :token
|
297
298
|
|
299
|
+
# Applicant Endorsements
|
300
|
+
create_table :applicant_endorsements do |t|
|
301
|
+
t.integer :applicant_id
|
302
|
+
t.string :applicant_type
|
303
|
+
|
304
|
+
t.integer :endorser_id
|
305
|
+
t.string :endorser_type
|
306
|
+
|
307
|
+
t.boolean :unknown_member, default: false
|
308
|
+
t.string :endorser_email
|
309
|
+
t.string :name
|
310
|
+
t.string :phone
|
311
|
+
|
312
|
+
t.string :status
|
313
|
+
t.text :status_steps
|
314
|
+
|
315
|
+
t.text :notes
|
316
|
+
t.boolean :accept_declaration
|
317
|
+
|
318
|
+
t.string :token
|
319
|
+
t.datetime :last_notified_at
|
320
|
+
|
321
|
+
t.datetime :created_at
|
322
|
+
t.datetime :updated_at
|
323
|
+
end
|
324
|
+
|
325
|
+
add_index :applicant_endorsements, :applicant_id
|
326
|
+
add_index :applicant_endorsements, :token
|
327
|
+
|
298
328
|
# Applicant Courses
|
299
329
|
create_table :applicant_course_areas do |t|
|
300
330
|
t.string :title
|
@@ -8,7 +8,7 @@ module EffectiveMemberships
|
|
8
8
|
[
|
9
9
|
:categories_table_name, :applicants_table_name, :applicant_reviews_table_name, :fee_payments_table_name, :organizations_table_name, :representatives_table_name,
|
10
10
|
:category_class_name, :organization_class_name, :applicant_class_name, :applicant_review_class_name, :fee_payment_class_name, :registrar_class_name, :membership_card_class_name,
|
11
|
-
:additional_fee_types, :applicant_reviews,
|
11
|
+
:additional_fee_types, :applicant_reviews, :applicant_endorsements_endorser_collection,
|
12
12
|
:layout,
|
13
13
|
:mailer, :parent_mailer, :deliver_method, :mailer_layout, :mailer_sender, :mailer_admin, :mailer_subject, :use_effective_email_templates
|
14
14
|
]
|
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.4.
|
4
|
+
version: 0.4.10
|
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-
|
11
|
+
date: 2022-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -178,6 +178,20 @@ dependencies:
|
|
178
178
|
- - ">="
|
179
179
|
- !ruby/object:Gem::Version
|
180
180
|
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: timecop
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
181
195
|
- !ruby/object:Gem::Dependency
|
182
196
|
name: effective_test_bot
|
183
197
|
requirement: !ruby/object:Gem::Requirement
|
@@ -242,6 +256,7 @@ files:
|
|
242
256
|
- app/assets/stylesheets/effective_memberships/base.scss
|
243
257
|
- app/controllers/admin/applicant_course_areas_controller.rb
|
244
258
|
- app/controllers/admin/applicant_course_names_controller.rb
|
259
|
+
- app/controllers/admin/applicant_endorsements_controller.rb
|
245
260
|
- app/controllers/admin/applicant_references_controller.rb
|
246
261
|
- app/controllers/admin/applicants_controller.rb
|
247
262
|
- app/controllers/admin/categories_controller.rb
|
@@ -252,6 +267,7 @@ files:
|
|
252
267
|
- app/controllers/admin/organizations_controller.rb
|
253
268
|
- app/controllers/admin/registrar_actions_controller.rb
|
254
269
|
- app/controllers/admin/representatives_controller.rb
|
270
|
+
- app/controllers/effective/applicant_endorsements_controller.rb
|
255
271
|
- app/controllers/effective/applicant_references_controller.rb
|
256
272
|
- app/controllers/effective/applicants_controller.rb
|
257
273
|
- app/controllers/effective/fee_payments_controller.rb
|
@@ -261,6 +277,7 @@ files:
|
|
261
277
|
- app/controllers/effective/representatives_controller.rb
|
262
278
|
- app/datatables/admin/effective_applicant_course_areas_datatable.rb
|
263
279
|
- app/datatables/admin/effective_applicant_course_names_datatable.rb
|
280
|
+
- app/datatables/admin/effective_applicant_endorsements_datatable.rb
|
264
281
|
- app/datatables/admin/effective_applicant_references_datatable.rb
|
265
282
|
- app/datatables/admin/effective_applicants_datatable.rb
|
266
283
|
- app/datatables/admin/effective_categories_datatable.rb
|
@@ -272,6 +289,7 @@ files:
|
|
272
289
|
- app/datatables/admin/effective_representatives_datatable.rb
|
273
290
|
- app/datatables/effective_applicant_courses_datatable.rb
|
274
291
|
- app/datatables/effective_applicant_educations_datatable.rb
|
292
|
+
- app/datatables/effective_applicant_endorsements_datatable.rb
|
275
293
|
- app/datatables/effective_applicant_experiences_datatable.rb
|
276
294
|
- app/datatables/effective_applicant_references_datatable.rb
|
277
295
|
- app/datatables/effective_applicants_datatable.rb
|
@@ -295,6 +313,7 @@ files:
|
|
295
313
|
- app/models/effective/applicant_course_area.rb
|
296
314
|
- app/models/effective/applicant_course_name.rb
|
297
315
|
- app/models/effective/applicant_education.rb
|
316
|
+
- app/models/effective/applicant_endorsement.rb
|
298
317
|
- app/models/effective/applicant_experience.rb
|
299
318
|
- app/models/effective/applicant_reference.rb
|
300
319
|
- app/models/effective/applicant_review.rb
|
@@ -313,6 +332,7 @@ files:
|
|
313
332
|
- app/views/admin/applicant_course_areas/_form_applicant_course_area.html.haml
|
314
333
|
- app/views/admin/applicant_course_areas/index.html.haml
|
315
334
|
- app/views/admin/applicant_course_name/_form.html.haml
|
335
|
+
- app/views/admin/applicant_endorsements/_applicant_endorsement.html.haml
|
316
336
|
- app/views/admin/applicant_references/_applicant_reference.html.haml
|
317
337
|
- app/views/admin/applicants/_form.html.haml
|
318
338
|
- app/views/admin/applicants/_form_approve.html.haml
|
@@ -352,6 +372,13 @@ files:
|
|
352
372
|
- app/views/admin/registrar_actions/_form_remove.html.haml
|
353
373
|
- app/views/admin/representatives/_form.html.haml
|
354
374
|
- app/views/admin/representatives/_user_fields.html.haml
|
375
|
+
- app/views/admin/users/_col.html.haml
|
376
|
+
- app/views/effective/applicant_endorsements/_applicant_endorsement.html.haml
|
377
|
+
- app/views/effective/applicant_endorsements/_datatable_actions.html.haml
|
378
|
+
- app/views/effective/applicant_endorsements/_form.html.haml
|
379
|
+
- app/views/effective/applicant_endorsements/_form_declaration.html.haml
|
380
|
+
- app/views/effective/applicant_endorsements/complete.html.haml
|
381
|
+
- app/views/effective/applicant_endorsements/edit.html.haml
|
355
382
|
- app/views/effective/applicant_references/_applicant_reference.html.haml
|
356
383
|
- app/views/effective/applicant_references/_datatable_actions.html.haml
|
357
384
|
- app/views/effective/applicant_references/_form.html.haml
|
@@ -365,6 +392,7 @@ files:
|
|
365
392
|
- app/views/effective/applicants/_declarations.html.haml
|
366
393
|
- app/views/effective/applicants/_demographics.html.haml
|
367
394
|
- app/views/effective/applicants/_education.html.haml
|
395
|
+
- app/views/effective/applicants/_endorsements.html.haml
|
368
396
|
- app/views/effective/applicants/_experience.html.haml
|
369
397
|
- app/views/effective/applicants/_files.html.haml
|
370
398
|
- app/views/effective/applicants/_layout.html.haml
|
@@ -382,6 +410,7 @@ files:
|
|
382
410
|
- app/views/effective/applicants/declarations.html.haml
|
383
411
|
- app/views/effective/applicants/demographics.html.haml
|
384
412
|
- app/views/effective/applicants/education.html.haml
|
413
|
+
- app/views/effective/applicants/endorsements.html.haml
|
385
414
|
- app/views/effective/applicants/experience.html.haml
|
386
415
|
- app/views/effective/applicants/files.html.haml
|
387
416
|
- app/views/effective/applicants/organization.html.haml
|
@@ -417,6 +446,7 @@ files:
|
|
417
446
|
- app/views/effective/memberships_mailer/applicant_approved.liquid
|
418
447
|
- app/views/effective/memberships_mailer/applicant_completed.liquid
|
419
448
|
- app/views/effective/memberships_mailer/applicant_declined.liquid
|
449
|
+
- app/views/effective/memberships_mailer/applicant_endorsement_notification.liquid
|
420
450
|
- app/views/effective/memberships_mailer/applicant_missing_info.liquid
|
421
451
|
- app/views/effective/memberships_mailer/applicant_reference_notification.liquid
|
422
452
|
- app/views/effective/organizations/_dashboard.html.haml
|