manager notifications

This commit is contained in:
Mark Moser 2017-02-09 16:26:33 -06:00
parent 8256343851
commit cb6dccded8
8 changed files with 320 additions and 2 deletions

View File

@ -5,6 +5,8 @@ class ReviewerVote < ApplicationRecord
validates :user_id, uniqueness: { scope: :candidate_id }
after_save :notify_manager
enum vote: {
undecided: 0,
yea: 1,
@ -15,4 +17,38 @@ class ReviewerVote < ApplicationRecord
approved: 1,
rejected: 2
}
private
def notify_manager
ReviewerMailer.notify_manager(candidate_id).deliver_now if all_reviewers_voted?
end
def all_reviewers_voted? # rubocop:disable Metrics/MethodLength
sql = " select distinct rev.candidate_id
, full_votes.voters, full_votes.vote_count
, c.test_hash
from reviewer_votes rev
inner join users u on u.id = rev.user_id
inner join candidates c on c.id = rev.candidate_id
left join (
select candidate_id
from reviewer_votes
where veto > 0 or veto is null
) as vetos on vetos.candidate_id = rev.candidate_id
left join (
select candidate_id
, count(vote) voters
, sum(case when vote != 0 then 1 else 0 end) vote_count
from reviewer_votes
left join users on users.id = reviewer_votes.user_id
where users.role != 'manager'
group by candidate_id
) as full_votes on full_votes.candidate_id = rev.candidate_id
where vetos.candidate_id is null
and full_votes.voters = full_votes.vote_count
and rev.candidate_id = #{candidate_id};"
result = ActiveRecord::Base.connection.exec_query(sql)
result.count == 1
end # rubocop:enable Metrics/MethodLength
end

View File

@ -19,6 +19,8 @@ class User < ApplicationRecord
end
# Voting
# TODO: Refactor this out of User, belongs on ReviewerVote
# ie: cast_yea(candidate, user)
def cast_yea_on candidate
vote = votes.find_by(candidate_id: candidate.to_i)
vote.vote = :yea

View File

@ -0,0 +1,10 @@
<row>
<columns class="email-body">
<p>Hello <%= @manager.name %>,</p>
<p>
Everyone has voted and you need to request or decline an interview for
<%= link_to nil, admin_result_url(@candidate.test_hash) %>
</p>
</columns>
</row>

View File

@ -0,0 +1,6 @@
PERFICIENT/digital SKILLS ASSESSMENT RESULTS
Hello <%= @manager.name %>,
Everyone has voted and you need to request or decline an interview for
<%= admin_result_url(@candidate.test_hash) %>

View File

@ -696,3 +696,197 @@ wade10:
created_at: <%= DateTime.now() - 36.hours - 40.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 20.minutes %>
jorge1:
candidate: jorge
question: Cras justo odio, dapibus ac facilisis in, egestas eget quam. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Nullam id dolor id nibh ultricies vehicula ut id elit.
answer: option 3
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 22.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 22.minutes %>
jorge2:
candidate: jorge
question: fed2
answer: 'indexOf()'
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 24.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 4.minutes %>
jorge3:
candidate: jorge
question: fed3
answer: {html: '<h1>Salmon</h1>', css: 'h1 {color: salmon;}', js: '', text: 'Gotta lotta GOOD things on sale, strangah.'}
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 26.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 6.minutes %>
jorge4:
candidate: jorge
question: fed4
answer: Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 28.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 28.minutes %>
jorge5:
candidate: jorge
question: fed5
answer: 'Dynamic listeners'
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 30.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 30.minutes %>
jorge6:
candidate: jorge
question: fed6
answer: Integer posuere erat a ante venenatis dapibus posuere velit aliquet.
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 32.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 12.minutes %>
jorge7:
candidate: jorge
question: fed7
answer: {html: '<p>This means <strong>jQuery</strong> needs to be available in live-coder!</p>', css: "strong {font-size: 1.6em;}\n.green {color: green;}", js: '$("strong").addClass("green");'}
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 34.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 14.minutes %>
jorge8:
candidate: jorge
question: fed8
answer:
other: Some generic user input
options:
- other
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 36.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 16.minutes %>
jorge9:
candidate: jorge
question: fed9
answer:
other: Brunch
options:
- Neither
- other
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 38.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 18.minutes %>
jorge10:
candidate: jorge
question: fed10
answer: ["Live long and prosper", "Who you calling Scruffy?"]
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 40.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 20.minutes %>
elsie1:
candidate: elsie
question: Cras justo odio, dapibus ac facilisis in, egestas eget quam. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Nullam id dolor id nibh ultricies vehicula ut id elit.
answer: option 3
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 22.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 22.minutes %>
elsie2:
candidate: elsie
question: fed2
answer: 'indexOf()'
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 24.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 4.minutes %>
elsie3:
candidate: elsie
question: fed3
answer: {html: '<h1>Salmon</h1>', css: 'h1 {color: salmon;}', js: '', text: 'Gotta lotta GOOD things on sale, strangah.'}
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 26.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 6.minutes %>
elsie4:
candidate: elsie
question: fed4
answer: Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 28.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 28.minutes %>
elsie5:
candidate: elsie
question: fed5
answer: 'Dynamic listeners'
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 30.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 30.minutes %>
elsie6:
candidate: elsie
question: fed6
answer: Integer posuere erat a ante venenatis dapibus posuere velit aliquet.
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 32.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 12.minutes %>
elsie7:
candidate: elsie
question: fed7
answer: {html: '<p>This means <strong>jQuery</strong> needs to be available in live-coder!</p>', css: "strong {font-size: 1.6em;}\n.green {color: green;}", js: '$("strong").addClass("green");'}
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 34.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 14.minutes %>
elsie8:
candidate: elsie
question: fed8
answer:
other: Some generic user input
options:
- other
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 36.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 16.minutes %>
elsie9:
candidate: elsie
question: fed9
answer:
other: Brunch
options:
- Neither
- other
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 38.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 18.minutes %>
elsie10:
candidate: elsie
question: fed10
answer: ["Live long and prosper", "Who you calling Scruffy?"]
saved: 0
submitted: true
created_at: <%= DateTime.now() - 36.hours - 40.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 20.minutes %>

View File

@ -116,6 +116,30 @@ wade: # Wade has completed AND submitted the test
reminded: false
test_hash: BkSkpapJnkz2N
jorge: # Jorge has completed AND submitted the test
name: Jorge Holmes
email: <%= CryptSerializer.dump 'jorge.holmes@mailinator.com' %>
experience: 0-3
project: Client/Project
recruiter: recruiter
quiz: fed
completed: true
completed_at: <%= DateTime.current %>
reminded: false
test_hash: iC5FdWJxcyySBmpOpU
elsie: # Elsie has completed AND submitted the test
name: Elsie Lowe
email: <%= CryptSerializer.dump 'elsie.lowe@mailinator.com' %>
experience: 0-3
project: Client/Project
recruiter: recruiter
quiz: fed
completed: true
completed_at: <%= DateTime.current %>
reminded: false
test_hash: rLSoizA3ATMNSCx
gustov: # Gustov is NOT for FED
name: Gustov
email: <%= CryptSerializer.dump 'gustov@mailinator.com' %>

View File

@ -66,3 +66,30 @@ reviewer2_wade:
candidate: wade
user: reviewer2
manager_jorge:
candidate: jorge
user: manager
reviewer_jorge:
candidate: jorge
user: reviewer
vote: 1
reviewer2_jorge:
candidate: jorge
user: reviewer2
manager_elsie:
candidate: elsie
user: manager
reviewer_elsie:
candidate: elsie
user: reviewer
reviewer2_elsie:
candidate: elsie
user: reviewer2

View File

@ -12,10 +12,11 @@ class ReviewerVoteTest < ActiveSupport::TestCase
assert_equal 3, richard.votes.size
end
test "manager has 4 votes" do
test "manager has a vote for every completed quiz" do
manager = users(:manager)
completed_count = Candidate.where(completed: true).count
assert_equal 4, manager.votes.size
assert_equal completed_count, manager.votes.size
end
test "richard has been approved" do
@ -31,4 +32,22 @@ class ReviewerVoteTest < ActiveSupport::TestCase
assert stacy.declined?
refute stacy.approved?
end
test "mailer is queued on last vote" do
reviewer = users(:reviewer2)
candidate = candidates(:jorge)
assert_difference("ActionMailer::Base.deliveries.size", 1) do
reviewer.cast_yea_on(candidate)
end
end
test "mailer is NOT queued on first vote" do
reviewer = users(:reviewer2)
candidate = candidates(:elsie)
assert_difference("ActionMailer::Base.deliveries.size", 0) do
reviewer.cast_yea_on(candidate)
end
end
end