diff --git a/app/models/volunteer.rb b/app/models/volunteer.rb index 1cf7af41f0..efb77d6b01 100644 --- a/app/models/volunteer.rb +++ b/app/models/volunteer.rb @@ -55,13 +55,14 @@ class Volunteer < User .order(:display_name) } - def self.email_court_report_reminder + def self.send_court_report_reminder active.includes(:case_assignments).where.not(case_assignments: nil).find_each do |volunteer| volunteer.case_assignments.active.each do |case_assignment| current_case = case_assignment.casa_case report_due_date = current_case.court_report_due_date if (report_due_date == Date.current + COURT_REPORT_SUBMISSION_REMINDER) && current_case.court_report_not_submitted? VolunteerMailer.court_report_reminder(volunteer, report_due_date) + CourtReportDueSmsReminderService.court_report_reminder(volunteer, report_due_date) end end end diff --git a/app/services/court_report_due_sms_reminder_service.rb b/app/services/court_report_due_sms_reminder_service.rb new file mode 100644 index 0000000000..a3f249aacb --- /dev/null +++ b/app/services/court_report_due_sms_reminder_service.rb @@ -0,0 +1,35 @@ +class CourtReportDueSmsReminderService + BASE_URL = Rails.application.credentials[:BASE_URL] + GENERATE_CASE_COURT_REPORT_LINK = "/case_court_reports" + + class << self + def court_report_reminder(user, report_due_date) + return if !user[:receive_sms_notifications] || user[:phone_number].blank? + + user_casa_org = user.casa_org + twilio_service = TwilioService.new(user_casa_org.twilio_api_key_sid, user_casa_org.twilio_api_key_secret, user_casa_org.twilio_account_sid) + sms_params = { + From: user_casa_org.twilio_phone_number, + Body: create_message(report_due_date), + To: user.phone_number + } + twilio_service.send_sms(sms_params) + end + + private + + def create_message(report_due_date) + "Your court report is due on #{report_due_date}. Generate a court report to complete & submit here: " + create_short_link + end + + def create_short_link + if BASE_URL.blank? + raise "BASE_URL environment variable not defined" + end + + short_url_service = ShortUrlService.new + short_url_service.create_short_url(BASE_URL + GENERATE_CASE_COURT_REPORT_LINK) + short_url_service.short_url + end + end +end diff --git a/lib/tasks/court_report_due_reminder.rake b/lib/tasks/court_report_due_reminder.rake index 663aa3b4b7..9bcac99c5b 100644 --- a/lib/tasks/court_report_due_reminder.rake +++ b/lib/tasks/court_report_due_reminder.rake @@ -1,4 +1,4 @@ desc "Send an email to volunteers when their court report is due in 1 week, run by heroku scheduler." task court_report_due_reminder: :environment do - Volunteer.email_court_report_reminder + Volunteer.send_court_report_reminder end diff --git a/spec/models/volunteer_spec.rb b/spec/models/volunteer_spec.rb index cb4d6bde8f..cea92f3a16 100644 --- a/spec/models/volunteer_spec.rb +++ b/spec/models/volunteer_spec.rb @@ -27,12 +27,24 @@ expect(VolunteerMailer).to receive(:court_report_reminder).with(v1, Date.current + 7.days) expect(VolunteerMailer).to_not receive(:court_report_reminder).with(v2, anything) expect(VolunteerMailer).to_not receive(:court_report_reminder).with(v3, anything) - described_class.email_court_report_reminder + described_class.send_court_report_reminder end it "should not send reminders about unassigned cases" do expect(VolunteerMailer).to_not receive(:court_report_reminder).with(v4, anything) - described_class.email_court_report_reminder + described_class.send_court_report_reminder + end + + it "sends one sms" do + expect(CourtReportDueSmsReminderService).to receive(:court_report_reminder).with(v1, Date.current + 7.days) + expect(CourtReportDueSmsReminderService).to_not receive(:court_report_reminder).with(v2, anything) + expect(CourtReportDueSmsReminderService).to_not receive(:court_report_reminder).with(v3, anything) + described_class.send_court_report_reminder + end + + it "should not send sms about unassigned cases" do + expect(CourtReportDueSmsReminderService).to_not receive(:court_report_reminder).with(v4, anything) + described_class.send_court_report_reminder end end diff --git a/spec/services/court_report_due_sms_reminder_service_spec.rb b/spec/services/court_report_due_sms_reminder_service_spec.rb new file mode 100644 index 0000000000..9fd81d01aa --- /dev/null +++ b/spec/services/court_report_due_sms_reminder_service_spec.rb @@ -0,0 +1,43 @@ +require "rails_helper" +require "support/stubbed_requests/webmock_helper" + +RSpec.describe TwilioService do + describe "court report due sms reminder service" do + let!(:volunteer) { create(:volunteer, receive_sms_notifications: true, phone_number: "+12223334444") } + let!(:report_due_date) { Date.current + 7.days } + + before :each do + WebMockHelper.short_io_court_report_due_date_stub + WebMockHelper.twilio_court_report_due_date_stub + WebMock.disable_net_connect! + end + + context "when sending sms reminder" do + it "should send a SMS with a short url successfully" do + response = CourtReportDueSmsReminderService.court_report_reminder(volunteer, report_due_date) + + expect(response.error_code).to match nil + expect(response.status).to match "sent" + expect(response.body).to match "Your court report is due on #{report_due_date}. Generate a court report to complete & submit here: https://42ni.short.gy/jzTwdF" + end + end + + context "when volunteer is not opted into sms notifications" do + let(:volunteer) { create(:volunteer, receive_sms_notifications: false) } + + it "should not send a SMS" do + response = CourtReportDueSmsReminderService.court_report_reminder(volunteer, report_due_date) + expect(response).to be_nil + end + end + + context "when volunteer does not have a valid phone number" do + let(:volunteer) { create(:volunteer, phone_number: nil) } + + it "should not send a SMS" do + response = CourtReportDueSmsReminderService.court_report_reminder(volunteer, report_due_date) + expect(response).to be_nil + end + end + end +end diff --git a/spec/support/stubbed_requests/short_io_api.rb b/spec/support/stubbed_requests/short_io_api.rb index fb81f061ba..1ef992de5f 100644 --- a/spec/support/stubbed_requests/short_io_api.rb +++ b/spec/support/stubbed_requests/short_io_api.rb @@ -28,4 +28,19 @@ def short_io_stub_localhost(base_url = "http://localhost:3000/case_contacts/new" ) .to_return(status: 200, body: "{\"shortURL\":\"https://42ni.short.gy/jzTwdF\"}", headers: {}) end + + def short_io_court_report_due_date_stub(base_url = "http://localhost:3000/case_court_reports") + WebMock.stub_request(:post, "https://api.short.io/links") + .with( + body: {originalURL: base_url, domain: "42ni.short.gy"}.to_json, + headers: { + "Accept" => "application/json", + "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3", + "Authorization" => "1337", + "Content-Type" => "application/json", + "User-Agent" => "Ruby" + } + ) + .to_return(status: 200, body: "{\"shortURL\":\"https://42ni.short.gy/jzTwdF\"}", headers: {}) + end end diff --git a/spec/support/stubbed_requests/twilio_api.rb b/spec/support/stubbed_requests/twilio_api.rb index a0d031586a..8797945412 100644 --- a/spec/support/stubbed_requests/twilio_api.rb +++ b/spec/support/stubbed_requests/twilio_api.rb @@ -45,4 +45,17 @@ def twilio_activation_error_stub(resource = "") ) .to_return(body: "{\"error_code\":\"42\", \"status\":\"failed\", \"body\":\"My tea's gone cold I wonder why\"}") end + + def twilio_court_report_due_date_stub(resource = "") + court_due_date = Date.current + 7.days + WebMock.stub_request(:post, "https://api.twilio.com/2010-04-01/Accounts/articuno34/Messages.json") + .with( + body: {"Body" => "Your court report is due on #{court_due_date}. Generate a court report to complete & submit here: https://42ni.short.gy/jzTwdF", "From" => "+15555555555", "To" => "+12223334444"}, + headers: { + "Content-Type" => "application/x-www-form-urlencoded", + "Authorization" => "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" + } + ) + .to_return(body: "{\"error_code\":null, \"status\":\"sent\", \"body\":\"Your court report is due on #{court_due_date}. Generate a court report to complete & submit here: https://42ni.short.gy/jzTwdF\"}") + end end