effective_memberships 0.6.13 → 0.7.0
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/applicant_reviews_controller.rb +19 -0
- data/app/controllers/effective/applicant_reviews_controller.rb +13 -0
- data/app/datatables/admin/effective_applicant_reviews_datatable.rb +24 -0
- data/app/datatables/effective_applicant_reviews_datatable.rb +25 -0
- data/app/datatables/effective_available_applicant_reviews_datatable.rb +40 -0
- data/app/mailers/effective/memberships_mailer.rb +43 -0
- data/app/models/concerns/effective_memberships_applicant.rb +23 -2
- data/app/models/concerns/effective_memberships_applicant_review.rb +34 -68
- data/app/models/concerns/effective_memberships_user.rb +6 -0
- data/app/views/admin/applicant_reviews/_applicant_review.html.haml +1 -0
- data/app/views/admin/applicants/_form_applicant.html.haml +4 -0
- data/app/views/admin/applicants/_status.html.haml +2 -2
- data/app/views/effective/applicant_reviews/_applicant_review.html.haml +4 -0
- data/app/views/effective/applicant_reviews/_content.html.haml +8 -0
- data/app/views/effective/applicant_reviews/_dashboard.html.haml +36 -0
- data/app/views/effective/applicant_reviews/_layout.html.haml +3 -0
- data/app/views/effective/applicant_reviews/_recommendation.html.haml +23 -0
- data/app/views/effective/applicant_reviews/_review.html.haml +1 -0
- data/app/views/effective/applicant_reviews/recommendation.html.haml +20 -0
- data/app/views/effective/applicant_reviews/review.html.haml +14 -0
- data/app/views/effective/applicant_reviews/start.html.haml +18 -0
- data/app/views/effective/applicant_reviews/submitted.html.haml +15 -0
- data/app/views/effective/applicants/_summary.html.haml +4 -3
- data/app/views/effective/memberships_mailer/applicant_review_submitted.liquid +19 -0
- data/config/routes.rb +6 -0
- data/lib/effective_memberships/version.rb +1 -1
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3972d4221b4931ed7f157f87ef8a7d9c9a1ad785679599a13c3d38e37fd48e56
|
4
|
+
data.tar.gz: 4a19e5c29db9c7ee41fd67177cda71197adb743f1f4eaaf97116192af82c562b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b5b013d0f0c7eddfbef6ed4b75c93169bfd4a48eebb07af26bb768d39f57285efb725266b26f6a75f05b14657ddb1ba9490594568b0deb65126caef3b873f99
|
7
|
+
data.tar.gz: cd37dded19f0ef05190120efe7749a6c0c3e71c5c53b53690c5d5e7e234a8b2b00e12db26480ee3e9f49617c505ca52499254d37b4ebd03c7e0918866e7af6d4
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Admin
|
2
|
+
class ApplicantReviewsController < 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
|
+
resource_scope -> { EffectiveMemberships.ApplicantReview.deep.all }
|
9
|
+
datatable -> { Admin::EffectiveApplicantReviewsDatatable.new }
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def permitted_params
|
14
|
+
model = (params.key?(:effective_applicant_review) ? :effective_applicant_review: :applicant_review)
|
15
|
+
params.require(model).permit!
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Effective
|
2
|
+
class ApplicantReviewsController < ApplicationController
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
4
|
+
|
5
|
+
include Effective::WizardController
|
6
|
+
|
7
|
+
resource_scope -> {
|
8
|
+
applicant = EffectiveMemberships.Applicant.find(params[:applicant_id])
|
9
|
+
EffectiveMemberships.ApplicantReview.deep.where(reviewer: current_user, applicant: applicant)
|
10
|
+
}
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Admin
|
2
|
+
class EffectiveApplicantReviewsDatatable < Effective::Datatable
|
3
|
+
datatable do
|
4
|
+
order :submitted_at
|
5
|
+
|
6
|
+
col :created_at, visible: false
|
7
|
+
col :id, visible: false
|
8
|
+
|
9
|
+
col :submitted_at, label: 'Reviewed', as: :date
|
10
|
+
col :reviewer
|
11
|
+
col :applicant
|
12
|
+
|
13
|
+
col :recommendation
|
14
|
+
col :comments
|
15
|
+
|
16
|
+
actions_col
|
17
|
+
end
|
18
|
+
|
19
|
+
collection do
|
20
|
+
EffectiveMemberships.ApplicantReview.deep.submitted
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Dashboard ApplicantReviews
|
2
|
+
class EffectiveApplicantReviewsDatatable < Effective::Datatable
|
3
|
+
datatable do
|
4
|
+
order :id, :desc
|
5
|
+
|
6
|
+
col :created_at, visible: false
|
7
|
+
col :id, visible: false
|
8
|
+
|
9
|
+
col :applicant
|
10
|
+
col :reviewer, visible: false
|
11
|
+
|
12
|
+
col :submitted_at, label: 'Reviewed', as: :date
|
13
|
+
col :recommendation
|
14
|
+
col :comments
|
15
|
+
|
16
|
+
actions_col(show: false) do |applicant_review|
|
17
|
+
dropdown_link_to('Show', effective_memberships.applicant_applicant_review_path(applicant_review.applicant, applicant_review))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
collection do
|
22
|
+
EffectiveMemberships.ApplicantReview.deep.submitted.where(reviewer: current_user)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Dashboard Available Applicant Reviews
|
2
|
+
class EffectiveAvailableApplicantReviewsDatatable < Effective::Datatable
|
3
|
+
datatable do
|
4
|
+
order :created_at
|
5
|
+
|
6
|
+
col :id, visible: false
|
7
|
+
|
8
|
+
col :created_at, label: 'Created', as: :date, visible: false
|
9
|
+
col :updated_at, label: 'Updated', as: :date, visible: false
|
10
|
+
col :submitted_at, label: 'Submitted', as: :date, visible: false
|
11
|
+
|
12
|
+
# This is when they become available for review
|
13
|
+
col :completed_at, label: 'Date', as: :date
|
14
|
+
|
15
|
+
col :user
|
16
|
+
col :category, label: 'Category'
|
17
|
+
col :to_status, label: 'Status'
|
18
|
+
|
19
|
+
actions_col(show: false) do |applicant|
|
20
|
+
applicant_review = applicant.applicant_review(reviewer: current_user)
|
21
|
+
|
22
|
+
if applicant_review.blank?
|
23
|
+
dropdown_link_to('Start Review', effective_memberships.new_applicant_applicant_review_path(applicant), 'data-turbolinks' => false)
|
24
|
+
elsif applicant_review.in_progress?
|
25
|
+
dropdown_link_to('Continue', effective_memberships.applicant_applicant_review_build_path(applicant, applicant_review, applicant_review.next_step), 'data-turbolinks' => false)
|
26
|
+
dropdown_link_to('Delete', effective_memberships.applicant_applicant_review_path(applicant, applicant_review), 'data-confirm': "Really delete #{applicant_review}?", 'data-method': :delete)
|
27
|
+
else
|
28
|
+
dropdown_link_to('Show', effective_memberships.applicant_applicant_review_path(applicant, applicant_review), 'data-turbolinks' => false)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
collection do
|
34
|
+
# These ones have already been submitted by this reviewer
|
35
|
+
submitted = EffectiveMemberships.ApplicantReview.deep.submitted.where(reviewer: current_user).select('applicant_id')
|
36
|
+
|
37
|
+
EffectiveMemberships.Applicant.deep.reviewable.where.not(id: submitted)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -64,6 +64,17 @@ module Effective
|
|
64
64
|
mail(to: resource.email, subject: subject, **headers)
|
65
65
|
end
|
66
66
|
|
67
|
+
def applicant_review_submitted(resource, opts = {})
|
68
|
+
@assigns = assigns_for(resource)
|
69
|
+
@applicant_review = resource
|
70
|
+
@applicant = resource.applicant
|
71
|
+
|
72
|
+
subject = subject_for(__method__, "Applicant Review for #{resource.applicant} submitted", resource, opts)
|
73
|
+
headers = headers_for(resource, opts)
|
74
|
+
|
75
|
+
mail(to: mailer_admin, subject: subject, **headers)
|
76
|
+
end
|
77
|
+
|
67
78
|
protected
|
68
79
|
|
69
80
|
def assigns_for(resource)
|
@@ -71,6 +82,10 @@ module Effective
|
|
71
82
|
return applicant_assigns(resource).merge(owner_assigns(resource.owner)).merge(membership_assigns(resource.owner.membership))
|
72
83
|
end
|
73
84
|
|
85
|
+
if resource.class.respond_to?(:effective_memberships_applicant_review?)
|
86
|
+
return applicant_review_assigns(resource).merge(applicant_assigns(resource.applicant)).merge(owner_assigns(resource.applicant.owner)).merge(membership_assigns(resource.applicant.owner.membership))
|
87
|
+
end
|
88
|
+
|
74
89
|
if resource.kind_of?(Effective::ApplicantEndorsement)
|
75
90
|
return endorsement_assigns(resource).merge(owner_assigns(resource.applicant.owner))
|
76
91
|
end
|
@@ -103,6 +118,23 @@ module Effective
|
|
103
118
|
{ applicant: values }
|
104
119
|
end
|
105
120
|
|
121
|
+
def applicant_review_assigns(applicant_review)
|
122
|
+
raise('expected an applicant review') unless applicant_review.class.respond_to?(:effective_memberships_applicant_review?)
|
123
|
+
|
124
|
+
values = {
|
125
|
+
date: (applicant_review.submitted_at || Time.zone.now).strftime('%F'),
|
126
|
+
submitted_at: (applicant_review.submitted_at&.strftime('%F') || 'not submitted'),
|
127
|
+
|
128
|
+
url: effective_memberships.applicant_applicant_review_url(applicant_review.applicant, applicant_review),
|
129
|
+
admin_url: effective_memberships.admin_applicant_review_url(applicant_review),
|
130
|
+
|
131
|
+
recommendation: applicant_review.recommendation.presence,
|
132
|
+
comments: applicant_review.comments.presence
|
133
|
+
}.compact
|
134
|
+
|
135
|
+
{ applicant_review: values }
|
136
|
+
end
|
137
|
+
|
106
138
|
def membership_assigns(membership)
|
107
139
|
return {} if membership.blank?
|
108
140
|
raise('expected a membership') unless membership.kind_of?(Effective::Membership)
|
@@ -149,5 +181,16 @@ module Effective
|
|
149
181
|
{ user: values }
|
150
182
|
end
|
151
183
|
|
184
|
+
def reviewer_assigns(owner)
|
185
|
+
raise('expected a owner') unless owner.class.respond_to?(:effective_memberships_owner?)
|
186
|
+
|
187
|
+
values = {
|
188
|
+
name: owner.to_s,
|
189
|
+
email: owner.email
|
190
|
+
}
|
191
|
+
|
192
|
+
{ reviewer: values }
|
193
|
+
end
|
194
|
+
|
152
195
|
end
|
153
196
|
end
|
@@ -187,6 +187,8 @@ module EffectiveMembershipsApplicant
|
|
187
187
|
|
188
188
|
scope :not_draft, -> { where.not(status: :draft) }
|
189
189
|
|
190
|
+
scope :reviewable, -> { where(status: :completed) }
|
191
|
+
|
190
192
|
scope :for, -> (user) {
|
191
193
|
raise('expected a effective memberships user') unless user.class.try(:effective_memberships_user?)
|
192
194
|
where(user: user).or(where(organization: user.organizations))
|
@@ -750,6 +752,10 @@ module EffectiveMembershipsApplicant
|
|
750
752
|
end
|
751
753
|
|
752
754
|
# Completed -> Reviewed requirements
|
755
|
+
def reviewable?
|
756
|
+
completed?
|
757
|
+
end
|
758
|
+
|
753
759
|
def applicant_reviews_required?
|
754
760
|
(min_applicant_reviews > 0 || applicant_reviews.present?)
|
755
761
|
end
|
@@ -758,6 +764,16 @@ module EffectiveMembershipsApplicant
|
|
758
764
|
category&.min_applicant_reviews.to_i
|
759
765
|
end
|
760
766
|
|
767
|
+
# Find
|
768
|
+
def applicant_review(reviewer:)
|
769
|
+
applicant_reviews.find { |ar| ar.reviewer_id == reviewer.id && ar.reviewer_type == reviewer.class.name }
|
770
|
+
end
|
771
|
+
|
772
|
+
# Find or build
|
773
|
+
def build_applicant_review(reviewer:)
|
774
|
+
applicant_review(reviewer: reviewer) || applicant_reviews.build(reviewer: reviewer)
|
775
|
+
end
|
776
|
+
|
761
777
|
# When an application is completed, these must be done to go to reviewed
|
762
778
|
# An Admin can override this and just set them to reviewed.
|
763
779
|
def reviewed_requirements
|
@@ -765,17 +781,22 @@ module EffectiveMembershipsApplicant
|
|
765
781
|
return requirements unless category.present?
|
766
782
|
|
767
783
|
if applicant_reviews_required?
|
768
|
-
requirements['Applicant Reviews'] = (applicant_reviews.count(&:
|
784
|
+
requirements['Applicant Reviews'] = (applicant_reviews.count(&:done?) >= min_applicant_reviews)
|
769
785
|
end
|
770
786
|
|
771
787
|
requirements
|
772
788
|
end
|
773
789
|
|
790
|
+
# Called when an applicant_review was submitted
|
791
|
+
def try_reviewed!
|
792
|
+
return false unless completed? && reviewed_requirements.values.all?
|
793
|
+
reviewed!
|
794
|
+
end
|
795
|
+
|
774
796
|
def review!
|
775
797
|
raise('applicant must have been submitted to review!') unless was_submitted?
|
776
798
|
|
777
799
|
# Let an admin ignore these requirements if need be
|
778
|
-
# return false unless completed? && reviewed_requirements.values.all?
|
779
800
|
reviewed!
|
780
801
|
end
|
781
802
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
# EffectiveMembershipsApplicantReview
|
4
4
|
#
|
5
|
-
# Mark your
|
5
|
+
# Mark your owner model with effective_memberships_applicant_review to get all the includes
|
6
6
|
|
7
7
|
module EffectiveMembershipsApplicantReview
|
8
8
|
extend ActiveSupport::Concern
|
@@ -22,82 +22,60 @@ module EffectiveMembershipsApplicantReview
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def recommendations
|
25
|
-
['
|
25
|
+
['Recommend Approve', 'Recommend Decline', 'Missing Information']
|
26
26
|
end
|
27
27
|
|
28
28
|
end
|
29
29
|
|
30
30
|
included do
|
31
|
-
log_changes if respond_to?(:log_changes)
|
31
|
+
log_changes(to: :applicant) if respond_to?(:log_changes)
|
32
32
|
|
33
33
|
acts_as_tokened
|
34
34
|
|
35
35
|
acts_as_statused(
|
36
|
-
:draft,
|
37
|
-
:
|
38
|
-
:accepted, # Accepted
|
39
|
-
:rejected # Rejected
|
36
|
+
:draft, # Just Started
|
37
|
+
:submitted # All Done
|
40
38
|
)
|
41
39
|
|
42
40
|
acts_as_wizard(
|
43
41
|
start: 'Start',
|
44
|
-
|
45
|
-
education: 'Education',
|
46
|
-
course_amounts: 'Courses',
|
47
|
-
experience: 'Work Experience',
|
48
|
-
references: 'References',
|
49
|
-
files: 'Attach Files',
|
50
|
-
declarations: 'Declarations',
|
42
|
+
review: 'Review Applicant',
|
51
43
|
recommendation: 'Recommendation',
|
52
44
|
submitted: 'Submitted'
|
53
45
|
)
|
54
46
|
|
47
|
+
scope :in_progress, -> { where(status: :draft) }
|
48
|
+
scope :done, -> { where(status: :submitted) }
|
49
|
+
|
55
50
|
belongs_to :applicant
|
56
51
|
belongs_to :reviewer, polymorphic: true
|
57
52
|
|
58
53
|
effective_resource do
|
59
54
|
submitted_at :datetime
|
60
|
-
recommendation :string
|
61
55
|
|
56
|
+
recommendation :string
|
62
57
|
comments :text # Rolling comments
|
63
58
|
|
64
|
-
# Conflict Step
|
65
|
-
conflict_of_interest :boolean
|
66
|
-
|
67
|
-
# Education Step
|
68
|
-
education_accepted :boolean
|
69
|
-
|
70
|
-
# Course Amounts
|
71
|
-
course_amounts_accepted :boolean
|
72
|
-
|
73
|
-
# Courses
|
74
|
-
courses_accepted :boolean
|
75
|
-
|
76
|
-
# Experience Step
|
77
|
-
experience_accepted :boolean
|
78
|
-
|
79
|
-
# References Step
|
80
|
-
references_accepted :boolean
|
81
|
-
|
82
|
-
# References Step
|
83
|
-
files_accepted :boolean
|
84
|
-
|
85
59
|
timestamps
|
86
60
|
end
|
87
61
|
|
88
|
-
scope :deep, -> { includes(:reviewer, applicant: :
|
62
|
+
scope :deep, -> { includes(:reviewer, applicant: :user) }
|
89
63
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
64
|
+
scope :for, -> (user) {
|
65
|
+
raise('expected a effective memberships user') unless user.class.try(:effective_memberships_user?)
|
66
|
+
where(reviewer: user)
|
67
|
+
}
|
94
68
|
|
95
|
-
|
69
|
+
with_options(if: -> { submitted? }) do
|
70
|
+
validates :recommendation, presence: true
|
96
71
|
|
97
|
-
|
72
|
+
validate do
|
73
|
+
self.errors.add(:recommendation, 'is invalid') unless EffectiveMemberships.ApplicantReview.recommendations.include?(recommendation)
|
74
|
+
end
|
75
|
+
end
|
98
76
|
|
99
77
|
def to_s
|
100
|
-
|
78
|
+
"Review of #{applicant}"
|
101
79
|
end
|
102
80
|
|
103
81
|
def in_progress?
|
@@ -105,43 +83,31 @@ module EffectiveMembershipsApplicantReview
|
|
105
83
|
end
|
106
84
|
|
107
85
|
def done?
|
108
|
-
|
86
|
+
submitted?
|
109
87
|
end
|
110
88
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
applicant.save!
|
116
|
-
|
117
|
-
after_commit { send_email(:applicant_review_conflict_of_interest) }
|
118
|
-
true
|
89
|
+
def can_visit_step?(step)
|
90
|
+
return (step == :submitted) if was_submitted?
|
91
|
+
can_revisit_completed_steps(step)
|
119
92
|
end
|
120
93
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
applicant.save!
|
126
|
-
|
127
|
-
after_commit { send_email(:applicant_review_completed) }
|
128
|
-
true
|
94
|
+
# Called by the recommendation wizard step
|
95
|
+
def recommendation!
|
96
|
+
submit!
|
129
97
|
end
|
130
98
|
|
131
|
-
def
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
applicant.save!
|
99
|
+
def submit!
|
100
|
+
submitted!
|
101
|
+
applicant.try_reviewed!
|
136
102
|
|
137
|
-
after_commit { send_email(:
|
103
|
+
after_commit { send_email(:applicant_review_submitted) }
|
138
104
|
true
|
139
105
|
end
|
140
106
|
|
141
107
|
private
|
142
108
|
|
143
109
|
def send_email(email)
|
144
|
-
EffectiveMemberships.send_email(email, self
|
110
|
+
EffectiveMemberships.send_email(email, self)
|
145
111
|
end
|
146
112
|
|
147
113
|
end
|
@@ -21,6 +21,7 @@ module EffectiveMembershipsUser
|
|
21
21
|
# App scoped
|
22
22
|
has_many :applicants, -> { order(:id) }, inverse_of: :user, as: :user
|
23
23
|
has_many :fee_payments, -> { order(:id) }, inverse_of: :user, as: :user
|
24
|
+
has_many :applicant_reviews, -> { order(:id) }, inverse_of: :reviewer, as: :reviewer
|
24
25
|
|
25
26
|
# Effective Scoped
|
26
27
|
has_many :representatives, -> { Effective::Representative.sorted },
|
@@ -85,4 +86,9 @@ module EffectiveMembershipsUser
|
|
85
86
|
membership_history_on(date).try(:membership_categories)
|
86
87
|
end
|
87
88
|
|
89
|
+
# Roles
|
90
|
+
def applicant_reviewer?
|
91
|
+
false
|
92
|
+
end
|
93
|
+
|
88
94
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
= render 'effective/applicant_reviews/applicant_review', applicant_review: applicant_review
|
@@ -17,6 +17,10 @@
|
|
17
17
|
= render 'effective/applicants/applicant', applicant: applicant, namespace: :admin
|
18
18
|
|
19
19
|
- # Just normal tabs now
|
20
|
+
- if applicant.applicant_reviews.present?
|
21
|
+
= tab 'Reviews' do
|
22
|
+
.mb-4= render_inline_datatable(Admin::EffectiveApplicantReviewsDatatable.new(applicant: applicant))
|
23
|
+
|
20
24
|
- if applicant.was_submitted? && !applicant.was_approved?
|
21
25
|
= tab 'Process' do
|
22
26
|
= render 'admin/applicants/form_process', applicant: applicant
|
@@ -107,10 +107,10 @@
|
|
107
107
|
- if applicant.reviewed_requirements['Applicant Reviews']
|
108
108
|
= icon('check', class: 'small-1')
|
109
109
|
|
110
|
-
= applicant.applicant_reviews.count(&:
|
110
|
+
= applicant.applicant_reviews.count(&:submitted?)
|
111
111
|
= '/'
|
112
112
|
= applicant.min_applicant_reviews
|
113
|
-
Reviews
|
113
|
+
Reviews Submitted
|
114
114
|
- else
|
115
115
|
%p
|
116
116
|
= icon('check', class: 'small-1')
|
@@ -0,0 +1,8 @@
|
|
1
|
+
- all_steps_content = resource.applicant&.category&.rich_text_applicant_review_all_steps_content
|
2
|
+
- step_content = resource.applicant&.category&.send("rich_text_applicant_review_#{step}_content")
|
3
|
+
|
4
|
+
- if all_steps_content.present?
|
5
|
+
.mb-2= all_steps_content
|
6
|
+
|
7
|
+
- if step_content.present?
|
8
|
+
.mb-2= step_content
|
@@ -0,0 +1,36 @@
|
|
1
|
+
- authorized = EffectiveResources.authorized?(self, :new, EffectiveMemberships.ApplicantReview)
|
2
|
+
|
3
|
+
- available = EffectiveResources.best('EffectiveAvailableApplicantReviewsDatatable').new(self)
|
4
|
+
- datatable = EffectiveResources.best('EffectiveApplicantReviewsDatatable').new(self)
|
5
|
+
|
6
|
+
- # In progress
|
7
|
+
- applicant_review = current_user.applicant_reviews.in_progress.first
|
8
|
+
|
9
|
+
- if applicant_review.present? && applicant_review.draft?
|
10
|
+
%h2 In-Progress Applicant Review
|
11
|
+
|
12
|
+
%p
|
13
|
+
Your review of #{applicant_review} is incomplete.
|
14
|
+
|
15
|
+
%p
|
16
|
+
Please
|
17
|
+
= link_to("Continue review", effective_memberships.applicant_applicant_review_build_path(applicant_review.applicant, applicant_review, applicant_review.next_step), 'data-turbolinks' => false, class: 'btn btn-primary')
|
18
|
+
or you can
|
19
|
+
= link_to('Abandon review', effective_memberships.applicant_applicant_review_path(applicant_review.applicant, applicant_review), 'data-confirm': "Really delete #{applicant_review}?", 'data-method': :delete, class: 'btn btn-danger')
|
20
|
+
to review again.
|
21
|
+
|
22
|
+
%hr
|
23
|
+
|
24
|
+
%h2 Applicant Reviews
|
25
|
+
|
26
|
+
- if available.present?
|
27
|
+
%p The following applicants are available for your review:
|
28
|
+
|
29
|
+
= render_simple_datatable(available)
|
30
|
+
- else
|
31
|
+
%p There are no applicants available for your review. When there are, we'll show them here.
|
32
|
+
|
33
|
+
- if datatable.present?
|
34
|
+
.mt-4
|
35
|
+
%h2 Review History
|
36
|
+
= render_datatable(datatable, simple: true)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
= wizard_card(applicant_review) do
|
2
|
+
%table.table
|
3
|
+
- if request.path.start_with?('/admin')
|
4
|
+
%tr
|
5
|
+
%th Reviewer
|
6
|
+
%td
|
7
|
+
- url = (polymorphic_admin_path(applicant_review.reviewer) rescue "/admin/users/#{applicant_review.reviewer.to_param}/edit")
|
8
|
+
= link_to(applicant_review.reviewer, url)
|
9
|
+
- else
|
10
|
+
%tr
|
11
|
+
%th Reviewer
|
12
|
+
%td
|
13
|
+
= applicant_review.reviewer.to_s
|
14
|
+
%br
|
15
|
+
= mail_to(applicant_review.reviewer.email)
|
16
|
+
|
17
|
+
%tr
|
18
|
+
%th Recommendation
|
19
|
+
%td= applicant_review.recommendation
|
20
|
+
|
21
|
+
%tr
|
22
|
+
%th Comments
|
23
|
+
%td= simple_format(applicant_review.comments.presence || 'none')
|
@@ -0,0 +1 @@
|
|
1
|
+
- # Intentionally blank
|
@@ -0,0 +1,20 @@
|
|
1
|
+
= render 'layout' do
|
2
|
+
= render 'effective/applicant_reviews/content', resource: resource
|
3
|
+
|
4
|
+
= card('Summary') do
|
5
|
+
= render 'effective/applicants/summary', applicant: resource.applicant
|
6
|
+
|
7
|
+
.mb-2
|
8
|
+
= collapse('Show application...', card_class: 'my-2') do
|
9
|
+
= render 'effective/applicants/applicant', applicant: resource.applicant
|
10
|
+
|
11
|
+
= card('Recommendation') do
|
12
|
+
|
13
|
+
= effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
|
14
|
+
= f.hidden_field :id
|
15
|
+
|
16
|
+
%p My recommendation is
|
17
|
+
= f.radios :recommendation, EffectiveMemberships.ApplicantReview.recommendations, label: false
|
18
|
+
= f.text_area :comments, label: 'Reviewer comments'
|
19
|
+
|
20
|
+
= f.save 'Submit Recommendation'
|
@@ -0,0 +1,14 @@
|
|
1
|
+
= render 'layout' do
|
2
|
+
= render 'effective/applicant_reviews/content', resource: resource
|
3
|
+
|
4
|
+
= card do
|
5
|
+
= render 'effective/applicants/summary', applicant: resource.applicant
|
6
|
+
= render 'effective/applicants/applicant', applicant: resource.applicant
|
7
|
+
|
8
|
+
= card do
|
9
|
+
= effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
|
10
|
+
= f.hidden_field :id
|
11
|
+
|
12
|
+
= f.text_area :comments, label: 'Reviewer comments'
|
13
|
+
|
14
|
+
= f.save 'Save and Continue'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
= render 'layout' do
|
2
|
+
= render 'effective/applicant_reviews/content', resource: resource
|
3
|
+
|
4
|
+
= card do
|
5
|
+
%p Welcome #{current_user}!
|
6
|
+
|
7
|
+
%p You are starting an applicant review for #{resource.applicant}.
|
8
|
+
|
9
|
+
= effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
|
10
|
+
= f.hidden_field :id
|
11
|
+
|
12
|
+
= f.hidden_field :applicant_type, value: f.object.applicant.class.name
|
13
|
+
= f.hidden_field :applicant_id
|
14
|
+
|
15
|
+
= f.hidden_field :reviewer_type
|
16
|
+
= f.hidden_field :reviewer_id
|
17
|
+
|
18
|
+
= f.save 'Save and Continue'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
= render 'layout' do
|
2
|
+
= render 'effective/applicant_reviews/content', resource: resource
|
3
|
+
|
4
|
+
- raise('expected a submitted applicant review') unless resource.was_submitted?
|
5
|
+
|
6
|
+
.alert.alert-success.mb-4
|
7
|
+
This review was submitted on #{resource.submitted_at.strftime('%F')}
|
8
|
+
|
9
|
+
.mb-4
|
10
|
+
= collapse('Show application...', card_class: 'my-2') do
|
11
|
+
= render 'effective/applicants/applicant', applicant: resource.applicant
|
12
|
+
|
13
|
+
= render 'effective/applicant_reviews/applicant_review', applicant_review: resource
|
14
|
+
|
15
|
+
= link_to "Return to Dashboard", root_path, class: 'btn btn-lg btn-primary btn-block'
|
@@ -54,11 +54,12 @@
|
|
54
54
|
%th Stream
|
55
55
|
%td= applicant.stream
|
56
56
|
|
57
|
-
-
|
57
|
+
- orders = applicant.orders.select { |order| EffectiveResources.authorized?(self, :show, order) }
|
58
|
+
- if orders.present?
|
58
59
|
%tr
|
59
|
-
%th Order#{'s' if
|
60
|
+
%th Order#{'s' if orders.length > 1}
|
60
61
|
%td
|
61
|
-
-
|
62
|
+
- orders.each do |order|
|
62
63
|
- if request.path.start_with?('/admin')
|
63
64
|
= link_to(order, effective_orders.edit_admin_order_path(order))
|
64
65
|
- else
|
@@ -0,0 +1,19 @@
|
|
1
|
+
---
|
2
|
+
subject: 'An applicant review has been submitted'
|
3
|
+
from: 'admin@example.com'
|
4
|
+
---
|
5
|
+
Hello admin,
|
6
|
+
|
7
|
+
The application for {{ user.name }} for {{ applicant.to_category }} has been reviewed by #{{ reviewer.name }}
|
8
|
+
|
9
|
+
They recommended {{ applicant_review.recommendation }} with the following comments:
|
10
|
+
|
11
|
+
{{ applicant_review.comments }}
|
12
|
+
|
13
|
+
For more details please visit
|
14
|
+
|
15
|
+
{{ applicant.admin_url }}
|
16
|
+
|
17
|
+
Thanks,
|
18
|
+
|
19
|
+
Have a great day!
|
data/config/routes.rb
CHANGED
@@ -7,6 +7,10 @@ EffectiveMemberships::Engine.routes.draw do
|
|
7
7
|
scope module: 'effective' do
|
8
8
|
resources :applicants, only: [:new, :show, :destroy] do
|
9
9
|
resources :build, controller: :applicants, only: [:show, :update]
|
10
|
+
|
11
|
+
resources :applicant_reviews, only: [:new, :show, :destroy] do
|
12
|
+
resources :build, controller: :applicant_reviews, only: [:show, :update]
|
13
|
+
end
|
10
14
|
end
|
11
15
|
|
12
16
|
resources :applicant_endorsements, only: [:new, :create, :show, :update] do
|
@@ -45,6 +49,8 @@ EffectiveMemberships::Engine.routes.draw do
|
|
45
49
|
post :notify, on: :member
|
46
50
|
end
|
47
51
|
|
52
|
+
resources :applicant_reviews, only: [:index, :show]
|
53
|
+
|
48
54
|
resources :fees
|
49
55
|
resources :categories, only: [:index, :edit, :update]
|
50
56
|
|
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
|
+
version: 0.7.0
|
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-09-
|
11
|
+
date: 2022-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -258,6 +258,7 @@ files:
|
|
258
258
|
- app/controllers/admin/applicant_course_names_controller.rb
|
259
259
|
- app/controllers/admin/applicant_endorsements_controller.rb
|
260
260
|
- app/controllers/admin/applicant_references_controller.rb
|
261
|
+
- app/controllers/admin/applicant_reviews_controller.rb
|
261
262
|
- app/controllers/admin/applicants_controller.rb
|
262
263
|
- app/controllers/admin/categories_controller.rb
|
263
264
|
- app/controllers/admin/fee_payments_controller.rb
|
@@ -270,6 +271,7 @@ files:
|
|
270
271
|
- app/controllers/admin/statuses_controller.rb
|
271
272
|
- app/controllers/effective/applicant_endorsements_controller.rb
|
272
273
|
- app/controllers/effective/applicant_references_controller.rb
|
274
|
+
- app/controllers/effective/applicant_reviews_controller.rb
|
273
275
|
- app/controllers/effective/applicants_controller.rb
|
274
276
|
- app/controllers/effective/fee_payments_controller.rb
|
275
277
|
- app/controllers/effective/membership_cards_controller.rb
|
@@ -280,6 +282,7 @@ files:
|
|
280
282
|
- app/datatables/admin/effective_applicant_course_names_datatable.rb
|
281
283
|
- app/datatables/admin/effective_applicant_endorsements_datatable.rb
|
282
284
|
- app/datatables/admin/effective_applicant_references_datatable.rb
|
285
|
+
- app/datatables/admin/effective_applicant_reviews_datatable.rb
|
283
286
|
- app/datatables/admin/effective_applicants_datatable.rb
|
284
287
|
- app/datatables/admin/effective_categories_datatable.rb
|
285
288
|
- app/datatables/admin/effective_fee_payments_datatable.rb
|
@@ -296,7 +299,9 @@ files:
|
|
296
299
|
- app/datatables/effective_applicant_equivalences_datatable.rb
|
297
300
|
- app/datatables/effective_applicant_experiences_datatable.rb
|
298
301
|
- app/datatables/effective_applicant_references_datatable.rb
|
302
|
+
- app/datatables/effective_applicant_reviews_datatable.rb
|
299
303
|
- app/datatables/effective_applicants_datatable.rb
|
304
|
+
- app/datatables/effective_available_applicant_reviews_datatable.rb
|
300
305
|
- app/datatables/effective_fee_payments_datatable.rb
|
301
306
|
- app/datatables/effective_memberships_directory_datatable.rb
|
302
307
|
- app/datatables/effective_organizations_datatable.rb
|
@@ -342,6 +347,7 @@ files:
|
|
342
347
|
- app/views/admin/applicant_course_name/_form.html.haml
|
343
348
|
- app/views/admin/applicant_endorsements/_applicant_endorsement.html.haml
|
344
349
|
- app/views/admin/applicant_references/_applicant_reference.html.haml
|
350
|
+
- app/views/admin/applicant_reviews/_applicant_review.html.haml
|
345
351
|
- app/views/admin/applicants/_form.html.haml
|
346
352
|
- app/views/admin/applicants/_form_applicant.html.haml
|
347
353
|
- app/views/admin/applicants/_form_approve.html.haml
|
@@ -395,6 +401,16 @@ files:
|
|
395
401
|
- app/views/effective/applicant_references/_form_declaration.html.haml
|
396
402
|
- app/views/effective/applicant_references/complete.html.haml
|
397
403
|
- app/views/effective/applicant_references/edit.html.haml
|
404
|
+
- app/views/effective/applicant_reviews/_applicant_review.html.haml
|
405
|
+
- app/views/effective/applicant_reviews/_content.html.haml
|
406
|
+
- app/views/effective/applicant_reviews/_dashboard.html.haml
|
407
|
+
- app/views/effective/applicant_reviews/_layout.html.haml
|
408
|
+
- app/views/effective/applicant_reviews/_recommendation.html.haml
|
409
|
+
- app/views/effective/applicant_reviews/_review.html.haml
|
410
|
+
- app/views/effective/applicant_reviews/recommendation.html.haml
|
411
|
+
- app/views/effective/applicant_reviews/review.html.haml
|
412
|
+
- app/views/effective/applicant_reviews/start.html.haml
|
413
|
+
- app/views/effective/applicant_reviews/submitted.html.haml
|
398
414
|
- app/views/effective/applicants/_applicant.html.haml
|
399
415
|
- app/views/effective/applicants/_content.html.haml
|
400
416
|
- app/views/effective/applicants/_course_amounts.html.haml
|
@@ -470,6 +486,7 @@ files:
|
|
470
486
|
- app/views/effective/memberships_mailer/applicant_endorsement_notification.liquid
|
471
487
|
- app/views/effective/memberships_mailer/applicant_missing_info.liquid
|
472
488
|
- app/views/effective/memberships_mailer/applicant_reference_notification.liquid
|
489
|
+
- app/views/effective/memberships_mailer/applicant_review_submitted.liquid
|
473
490
|
- app/views/effective/organizations/_dashboard.html.haml
|
474
491
|
- app/views/effective/organizations/_form.html.haml
|
475
492
|
- app/views/effective/organizations/_form_organization.html.haml
|