Skip to content

Commit 53b67ac

Browse files
committed
Merge pull request code-dot-org#4467 from code-dot-org/fix-workshop-surveys
fix workshop surveys
2 parents eb4e019 + 4e0a5f5 commit 53b67ac

File tree

8 files changed

+222
-56
lines changed

8 files changed

+222
-56
lines changed

dashboard/app/mailers/ops_mailer.rb

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ def script_assigned(params)
2222
end
2323

2424
def unexpected_teacher_added(user, added_teachers, workshop)
25+
@user = user
2526
@added_teachers = added_teachers
2627
@workshop = workshop
27-
@user = user
2828

2929
subject = "[ops notification] #{user.email} has added unexpected teachers to #{workshop.name}"
3030
mail content_type: 'text/html', subject: subject
@@ -34,11 +34,10 @@ def workshop_reminder(workshop, recipient)
3434
@workshop = workshop
3535
@recipient = recipient
3636

37-
subject = "Important: Your #{@workshop.phase_info[:long_name]} workshop is coming up in
37+
subject = "Important: Your #{@workshop.phase_long_name} workshop is coming up in
3838
#{(@workshop.segments.first.start.to_date - Date.today).to_i} days"
39-
if @workshop.phase_info[:prerequisite_phase]
40-
@prerequisite_phase = ActivityConstants::PHASES[@workshop.phase_info[:prerequisite_phase]]
41-
subject += ". Complete #{@prerequisite_phase[:long_name]}"
39+
if @workshop.prerequisite_phase
40+
subject += ". Complete #{@workshop.prerequisite_phase[:long_name]}"
4241
end
4342

4443
mail content_type: 'text/html', subject: subject, to: @recipient.email, from: 'pd@code.org'

dashboard/app/models/workshop.rb

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
# index_workshops_on_program_type (program_type)
1818
#
1919

20+
require 'cdo/activity_constants'
21+
2022
class Workshop < ActiveRecord::Base
2123
PROGRAM_TYPES = %w(1 2 3 4 5 6)
2224

@@ -46,49 +48,67 @@ class Workshop < ActiveRecord::Base
4648
association_foreign_key: 'facilitator_id',
4749
join_table: 'facilitators_workshops'
4850

49-
def self.workshops_ending_today
51+
def self.ending_today
5052
Workshop.joins(:segments).group(:workshop_id).having("(DATE(MAX(start)) = ?)", Date.today)
5153
end
5254

53-
def self.workshops_in_2_weeks
55+
def self.in_2_weeks
5456
Workshop.joins(:segments).group(:workshop_id).having("(DATE(MIN(start)) = DATE_ADD(?, INTERVAL 2 WEEK))", Date.today)
5557
end
5658

57-
def self.workshops_in_3_days
59+
def self.in_3_days
5860
Workshop.joins(:segments).group(:workshop_id).having("DATE(MIN(start)) = (DATE_ADD(?, INTERVAL 3 DAY))", Date.today)
5961
end
6062

6163
def phase_info
6264
ActivityConstants::PHASES[self.phase]
6365
end
6466

65-
def program_type_info
66-
ActivityConstants::PHASES[self.program_type.to_i]
67+
def phase_long_name
68+
return nil unless phase_info
69+
phase_info[:long_name]
6770
end
6871

69-
def self.send_automated_emails
70-
[Workshop.workshops_in_2_weeks, Workshop.workshops_in_3_days, Workshop.workshops_ending_today].each do |workshop_list|
71-
workshop_list.each do |workshop|
72-
teachers = workshop.teachers
73-
drop_ins = workshop.unexpected_teachers
74-
facilitators = workshop.facilitators
75-
district_contacts = workshop.district_contacts
76-
[teachers, drop_ins, facilitators, district_contacts].each do |recipient_list|
77-
recipient_list.each do |recipient|
78-
if EmailValidator::email_address?(recipient.email)
79-
if workshop.segments.first.start.to_date == Date.today
80-
logger.debug("Sending exit survey info to #{recipient.email}")
81-
OpsMailer.exit_survey_information(workshop, recipient).deliver_now
82-
else
83-
logger.debug("Sending email reminder to #{recipient.email}")
84-
OpsMailer.workshop_reminder(workshop, recipient).deliver_now
85-
end
86-
else
87-
logger.debug("Cannot send email to #{recipient.email} because it is not a valid email address")
88-
end
89-
end
90-
end
91-
end
72+
def prerequisite_phase
73+
return nil unless phase_info
74+
ActivityConstants::PHASES[phase_info[:prerequisite_phase]]
75+
end
76+
77+
def automated_email_recipients
78+
(teachers + unexpected_teachers + facilitators + district_contacts).uniq
79+
end
80+
81+
def send_reminders
82+
automated_email_recipients.each do |recipient|
83+
next unless EmailValidator::email_address?(recipient.email)
84+
logger.debug("Sending email reminder to #{recipient.email}")
85+
OpsMailer.workshop_reminder(self, recipient).deliver_now
86+
end
87+
end
88+
89+
def self.send_2_week_reminders
90+
in_2_weeks.each(&:send_reminders)
91+
end
92+
93+
def self.send_3_day_reminders
94+
in_3_days.each(&:send_reminders)
95+
end
96+
97+
def send_exit_surveys
98+
automated_email_recipients.each do |recipient|
99+
next unless EmailValidator::email_address?(recipient.email)
100+
logger.debug("Sending exit survey info to #{recipient.email}")
101+
OpsMailer.exit_survey_information(self, recipient).deliver_now
92102
end
93103
end
104+
105+
def self.send_exit_surveys
106+
ending_today.each(&:send_exit_surveys)
107+
end
108+
109+
def self.send_automated_emails
110+
send_2_week_reminders
111+
send_3_day_reminders
112+
send_exit_surveys
113+
end
94114
end

dashboard/app/views/ops_mailer/exit_survey_information.html.haml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
%p
22
Dear #{@recipient.ops_first_name},
33
%p
4-
Thanks for attending your #{@workshop.phase_info[:long_name]} in-person workshop.
4+
Thanks for attending your #{@workshop.phase_long_name} in-person workshop.
55
= render partial: 'exit_survey_url', locals: {workshop: @workshop, link_text: "short survey"}
66
- if @workshop.phase == 2
77
%p
@@ -21,4 +21,4 @@
2121
Check out this PDF
2222
for the many ways you can stay in touch with this community.
2323
%p
24-
The Code.org PD team
24+
The Code.org PD team

dashboard/app/views/ops_mailer/workshop_reminder.html.haml

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
%p
22
Dear #{@recipient.ops_first_name},
33
%p
4-
We’re looking forward to seeing you at your #{@workshop.phase_info[:long_name]} workshop on #{@workshop.segments.first.start.strftime("%A, %B %d")}! Together with your peers and facilitators, you’ll gain the support and resources you need to make a difference at your school.
4+
We’re looking forward to seeing you at your #{@workshop.phase_long_name} workshop on #{@workshop.segments.first.start.strftime("%A, %B %d")}! Together with your peers and facilitators, you’ll gain the support and resources you need to make a difference at your school.
55
%p
66
As part of your commitment to this program, you are expected to participate in this workshop. If you have any conflicts with these dates, please email
77
%a{href:'mailto:pd@code.org'}
@@ -34,24 +34,23 @@
3434
%h3
3535
What to bring
3636
- if @workshop.phase == 2
37-
-if @workshop.program_type.to_i == 3
37+
- if @workshop.program_type.to_i == 3
3838
%p
3939
Laptop (optional), water bottle, and snacks
40-
-else
40+
- else
4141
%p
4242
Laptop and charger, water bottle, and snacks
43-
- elsif @workshop.phase >= 4 && @workshop.phase <= 8
44-
-if @workshop.program_type.to_i == 3
43+
- elsif @workshop.phase && (@workshop.phase >= 4 && @workshop.phase <= 8)
44+
- if @workshop.program_type.to_i == 3
4545
%p
4646
Curriculum guide, green journal, laptop and charger, water bottle, and snacks
47-
-else
47+
- else
4848
%p
4949
Curriculum guide, laptop and charger, water bottle, and snacks
50-
-if @workshop.instructions.to_s != ''
51-
%h3
52-
Notes
53-
%p
54-
#{@workshop.instructions}
50+
51+
- if @workshop.instructions.to_s != ''
52+
%h3 Notes
53+
%p= @workshop.instructions
5554
%p
5655
See you soon,
5756
%br

dashboard/test/factories.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@
250250
end
251251

252252
factory :workshop do
253-
name 'My Workshop'
253+
sequence(:name) { |n| "My Workshop #{n}" }
254254
program_type '1'
255255
location 'Somewhere, USA'
256256
instructions 'Test workshop instructions.'

dashboard/test/mailers/ops_mailer_test.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ class OpsMailerTest < ActionMailer::TestCase
1515
assert_match "added 1 teachers", mail.body.encoded
1616
end
1717

18+
# see also tests in WorkshopTest
19+
1820
test "workshop_in_2_weeks_reminder" do
1921
# Create a workshop that starts 14 days from now. Include other segments for authenticity
2022
@workshop_1 = create_workshop(['abc@code.org', 'xyz@code.org'], 'facilitator_1@code.org', 'district_contact_1@code.org', Date.today + 14.day)
@@ -44,7 +46,7 @@ class OpsMailerTest < ActionMailer::TestCase
4446
incorrect_recipients.each do |email|
4547
assert_equal false, correct_recipients.include?(email)
4648
end
47-
assert_equal [@workshop_1], Workshop.workshops_in_2_weeks
49+
assert_equal [@workshop_1], Workshop.in_2_weeks
4850
end
4951

5052
test "workshop_in_3_days_reminder" do
@@ -76,7 +78,7 @@ class OpsMailerTest < ActionMailer::TestCase
7678
incorrect_recipients.each do |email|
7779
assert_equal false, correct_recipients.include?(email)
7880
end
79-
assert_equal [@workshop_1], Workshop.workshops_in_3_days
81+
assert_equal [@workshop_1], Workshop.in_3_days
8082
end
8183

8284
test "exit_survey_information" do
@@ -107,7 +109,7 @@ class OpsMailerTest < ActionMailer::TestCase
107109
incorrect_recipients.each do |email|
108110
assert_equal false, correct_recipients.include?(email)
109111
end
110-
assert_equal [@workshop_1], Workshop.workshops_ending_today
112+
assert_equal [@workshop_1], Workshop.ending_today
111113
end
112114

113115
# Only supports two teachers as an array and one facilitator as a string.
Lines changed: 148 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,152 @@
11
require 'test_helper'
22

33
class WorkshopTest < ActiveSupport::TestCase
4-
# test "the truth" do
5-
# assert true
6-
# end
4+
# see also tests in OpsMailerTest
5+
6+
def create_workshop(segment_starts_and_ends)
7+
create(:workshop).tap do |workshop|
8+
next if segment_starts_and_ends.blank?
9+
10+
workshop.segments = []
11+
segment_starts_and_ends.each do |segment_start_and_end|
12+
workshop.segments.build(start: segment_start_and_end.first,
13+
end: segment_start_and_end.last)
14+
end
15+
workshop.save!
16+
17+
end
18+
end
19+
20+
setup do
21+
@old_workshop = create_workshop [[Time.now.utc - 10.days, Time.now.utc - 9.days]]
22+
@tomorrow_workshop = create_workshop [[Time.now.utc + 1.days, Time.now.utc + 1.days + 1.hour]]
23+
24+
now = Time.zone.today
25+
today_start = Time.new(now.year, now.month, now.mday, 9, 0, 0, 0)
26+
today_end = Time.new(now.year, now.month, now.mday, 17, 0, 0, 0)
27+
28+
@today_workshop = create_workshop [[today_start, today_end]]
29+
# give this one a phase
30+
@today_workshop.phase = 1
31+
@today_workshop.save!
32+
33+
@today_ending_workshop = create_workshop [[today_start - 5.days, today_end - 5.days], [today_start + 5.minutes, today_end + 5.minutes]]
34+
@today_starting_workshop = create_workshop [[today_start + 5.days, today_end + 5.days], [today_start + 5.minutes, today_end + 5.minutes]]
35+
36+
@workshop_in_2_weeks = create_workshop [[today_start + 2.weeks, today_end + 2.weeks]]
37+
38+
@workshop_in_3_days = create_workshop [[today_start + 3.days, today_end + 3.days]]
39+
end
40+
41+
test "workshops ending today" do
42+
assert_equal [@today_workshop, @today_ending_workshop], Workshop.ending_today
43+
end
44+
45+
test "workshops in 2 weeks" do
46+
assert_equal [@workshop_in_2_weeks], Workshop.in_2_weeks
47+
end
48+
49+
test "workshops in 3 days" do
50+
assert_equal [@workshop_in_3_days], Workshop.in_3_days
51+
end
52+
53+
test "automated_email_recipients" do
54+
expected_recipients = Set.new
55+
56+
# just a workshop with a facilitator
57+
workshop = create :workshop
58+
expected_recipients << workshop.facilitators.first
59+
60+
assert_equal expected_recipients, Set.new(workshop.automated_email_recipients)
61+
62+
# add a district contact
63+
create :district_contact # not this one
64+
dc = create :district_contact
65+
district = create :district, contact: dc
66+
cohort = workshop.cohorts.first
67+
cohort.districts << district
68+
cohort.save!
69+
expected_recipients << dc
70+
71+
workshop = workshop.reload
72+
assert_equal expected_recipients, Set.new(workshop.automated_email_recipients)
73+
74+
# add some teachers
75+
create :teacher
76+
create :teacher
77+
t1 = create :teacher
78+
t2 = create :teacher
79+
80+
cohort = workshop.cohorts.first
81+
cohort.teachers << t1
82+
cohort.teachers << t2
83+
cohort.save!
84+
85+
expected_recipients << t1
86+
expected_recipients << t2
87+
88+
workshop = workshop.reload
89+
assert_equal expected_recipients, Set.new(workshop.automated_email_recipients)
90+
91+
# add another cohort
92+
cohort = create :cohort
93+
cohort.teachers << create(:teacher)
94+
expected_recipients << cohort.teachers.first
95+
cohort.save!
96+
workshop.cohorts << cohort
97+
workshop.save!
98+
99+
workshop = workshop.reload
100+
assert_equal expected_recipients, Set.new(workshop.automated_email_recipients)
101+
102+
# add an unexpected teacher
103+
t = create :teacher
104+
workshop.unexpected_teachers << t
105+
expected_recipients << t
106+
workshop.save!
107+
108+
workshop = workshop.reload
109+
assert_equal expected_recipients, Set.new(workshop.automated_email_recipients)
110+
end
111+
112+
test "send automated emails" do
113+
Workshop.send_automated_emails
114+
115+
assert_equal 11, ActionMailer::Base.deliveries.count
116+
117+
subjects = ActionMailer::Base.deliveries.map(&:subject)
118+
119+
assert_equal 7, subjects.grep(/confirmation instructions/).count
120+
assert_equal 1, subjects.grep(/Important: Your workshop is coming up in 14 days/).count
121+
assert_equal 1, subjects.grep(/Important: Your workshop is coming up in 3 days/).count
122+
assert_equal 2, subjects.grep(/Feedback requested for your Code.org PD workshop/).count
123+
end
124+
125+
test "phase long name" do
126+
# from ActivityConstants
127+
# PHASES = {
128+
# 1 => {id: 1, short_name: 'Phase 1', long_name: 'Phase 1: Online Introduction'},
129+
# 2 => {id: 2, short_name: 'Phase 2', long_name: 'Phase 2: Blended Summer Study', prerequisite_phase: 1},
130+
131+
assert_equal 'Phase 1: Online Introduction', create(:workshop, phase: 1).phase_long_name
132+
assert_equal 'Phase 2: Blended Summer Study', create(:workshop, phase: 2).phase_long_name
133+
134+
assert_equal nil, create(:workshop, phase: "????").phase_long_name
135+
assert_equal nil, create(:workshop, phase: nil).phase_long_name
136+
end
137+
138+
test "prerequisite phase" do
139+
# from ActivityConstants
140+
# PHASES = {
141+
# 1 => {id: 1, short_name: 'Phase 1', long_name: 'Phase 1: Online Introduction'},
142+
# 2 => {id: 2, short_name: 'Phase 2', long_name: 'Phase 2: Blended Summer Study', prerequisite_phase: 1},
143+
144+
assert_equal nil, create(:workshop, phase: 1).prerequisite_phase
145+
phase1 = {id: 1, short_name: 'Phase 1', long_name: 'Phase 1: Online Introduction'}
146+
assert_equal phase1, create(:workshop, phase: 2).prerequisite_phase
147+
assert_equal nil, create(:workshop, phase: 3).prerequisite_phase
148+
149+
assert_equal nil, create(:workshop, phase: "????").prerequisite_phase
150+
assert_equal nil, create(:workshop, phase: nil).prerequisite_phase
151+
end
7152
end

0 commit comments

Comments
 (0)