mirror of
https://github.com/edcommonwealth/sqm-dashboards.git
synced 2026-03-07 21:48:16 -08:00
working on recipient_schedule relationships
This commit is contained in:
parent
b0e65da944
commit
64996c422a
15 changed files with 161 additions and 72 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -19,3 +19,4 @@
|
|||
|
||||
# Ignore Byebug command history file.
|
||||
.byebug_history
|
||||
config/local_env.yml
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ class Attempt < ApplicationRecord
|
|||
belongs_to :recipient_schedule
|
||||
belongs_to :question
|
||||
|
||||
|
||||
def send_message
|
||||
twilio_number = ENV['TWILIO_NUMBER']
|
||||
client = Twilio::REST::Client.new ENV['TWILIO_ACCOUNT_SID'], ENV['TWILIO_AUTH_TOKEN']
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
class RecipientList < ApplicationRecord
|
||||
belongs_to :school
|
||||
|
||||
validates_associated :school
|
||||
validates :name, presence: true
|
||||
validates :recipient_ids, presence: true
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,11 @@ class RecipientSchedule < ApplicationRecord
|
|||
belongs_to :schedule
|
||||
has_many :attempts
|
||||
|
||||
validates_associated :recipient
|
||||
validates_associated :schedule
|
||||
|
||||
scope :ready, -> { where('next_attempt_at <= ?', Time.new) }
|
||||
scope :for, -> (recipient) { where(recipient_id: recipient.id) }
|
||||
|
||||
def next_question
|
||||
upcoming = upcoming_question_ids.split(/,/)
|
||||
|
|
@ -19,8 +23,9 @@ class RecipientSchedule < ApplicationRecord
|
|||
)
|
||||
|
||||
if attempt.send_message
|
||||
return if upcoming_question_ids.blank?
|
||||
upcoming = upcoming_question_ids.split(/,/)[1..-1].join(',')
|
||||
attempted = (attempted_question_ids.split(/,/) + [question.id]).join(',')
|
||||
attempted = ((attempted_question_ids.try(:split, /,/) || []) + [question.id]).join(',')
|
||||
update_attributes(
|
||||
upcoming_question_ids: upcoming,
|
||||
attempted_question_ids: attempted,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,22 @@ class Schedule < ApplicationRecord
|
|||
validates :recipient_list, presence: true
|
||||
validates :question_list, presence: true
|
||||
|
||||
after_create :create_recipient_schedules
|
||||
|
||||
scope :active, -> { where(active: true).where("start_date <= ? and end_date > ?", Date.today, Date.today) }
|
||||
|
||||
private
|
||||
|
||||
def create_recipient_schedules
|
||||
recipient_list.recipients.each do |recipient|
|
||||
question_ids = question_list.question_ids.split(/,/)
|
||||
question_ids = question_ids.shuffle if random
|
||||
recipient_schedules.create(
|
||||
recipient: recipient,
|
||||
upcoming_question_ids: question_ids.join(','),
|
||||
next_attempt_at: Time.new
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
%ul
|
||||
- question_list.errors.full_messages.each do |message|
|
||||
%li= message
|
||||
.field
|
||||
.form-group
|
||||
= f.label :name
|
||||
= f.text_field :name, class: 'form-control'
|
||||
.field
|
||||
.form-group
|
||||
= f.label :description
|
||||
= f.text_area :description, class: 'form-control'
|
||||
.form-group
|
||||
|
|
|
|||
|
|
@ -1,4 +1,12 @@
|
|||
Rails.application.configure do
|
||||
|
||||
config.before_configuration do
|
||||
env_file = File.join(Rails.root, 'config', 'local_env.yml')
|
||||
YAML.load(File.open(env_file)).each do |key, value|
|
||||
ENV[key.to_s] = value
|
||||
end if File.exists?(env_file)
|
||||
end
|
||||
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# In the development environment your application's code is reloaded on
|
||||
|
|
|
|||
|
|
@ -20,9 +20,17 @@ require 'rails_helper'
|
|||
|
||||
RSpec.describe SchedulesController, type: :controller do
|
||||
|
||||
let(:school) { School.create!(name: 'School') }
|
||||
let(:recipient_list) { RecipientList.create!(name: 'Parents', recipient_id_array: [1, 2, 3]) }
|
||||
let(:question_list) { QuestionList.create!(name: 'Parents Questions', question_id_array: [1, 2, 3]) }
|
||||
let!(:school) { School.create!(name: 'School') }
|
||||
|
||||
let!(:recipients) { create_recipients(school, 3) }
|
||||
let!(:recipient_list) do
|
||||
school.recipient_lists.create!(name: 'Parents', recipient_ids: recipients.map(&:id).join(','))
|
||||
end
|
||||
|
||||
let!(:questions) { create_questions(3) }
|
||||
let!(:question_list) do
|
||||
QuestionList.create!(name: 'Parent Questions', question_ids: questions.map(&:id).join(','))
|
||||
end
|
||||
|
||||
# This should return the minimal set of attributes required to create a valid
|
||||
# Schedule. As you add validations to Schedule, be sure to
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ require 'rails_helper'
|
|||
describe "survey:attempt_qustions" do
|
||||
include_context "rake"
|
||||
|
||||
let(:ready_recipient_schedule) { double('ready recipient schedule', attempt_question: nil) }
|
||||
let(:ready_recipient_schedule) { double('ready recipient schedule', attempt_question: nil) }
|
||||
let(:recipient_schedules) { double("recipient schedules", ready: [ready_recipient_schedule]) }
|
||||
let(:active_schedule) { double("active schedule", recipient_schedules: recipient_schedules) }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,17 @@ require 'rails_helper'
|
|||
|
||||
RSpec.describe Attempt, type: :model do
|
||||
|
||||
let(:question) { Question.create!(text: 'What is the question?', option1: 'A', option2: 'B', option3: 'C', option4: 'D', option5: 'E')}
|
||||
let(:question_list) { QuestionList.create(name: 'Parent Questions', question_ids: "#{question.id},2,3")}
|
||||
let!(:school) { School.create!(name: 'School') }
|
||||
|
||||
let(:recipient) { Recipient.create!(name: 'Parent', phone: '1112223333') }
|
||||
let(:recipient_list) { RecipientList.create(name: 'Parent List', recipient_ids: recipient.id.to_s)}
|
||||
let!(:recipient) { create_recipients(school, 1).first }
|
||||
let!(:recipient_list) do
|
||||
school.recipient_lists.create!(name: 'Parents', recipient_ids: "#{recipient.id}")
|
||||
end
|
||||
|
||||
let!(:question) { create_questions(1).first }
|
||||
let!(:question_list) do
|
||||
QuestionList.create!(name: 'Parent Questions', question_ids: "#{question.id}")
|
||||
end
|
||||
|
||||
let(:schedule) { Schedule.create!(name: 'Parent Schedule', recipient_list_id: recipient_list.id, question_list: question_list) }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
require 'rails_helper'
|
||||
|
||||
describe Recipient do
|
||||
describe RecipientList do
|
||||
describe "Save" do
|
||||
|
||||
it "should convert the recipient_id_array into the recipient_ids attribute" do
|
||||
recipient_list = RecipientList.create(name: 'Name', recipient_id_array: ['', '1', '2', '3'])
|
||||
expect(recipient_list).to be_a(RecipientList)
|
||||
|
|
@ -12,6 +11,11 @@ describe Recipient do
|
|||
recipient_list.update(recipient_id_array: ['3', '', '4', '5', '6'])
|
||||
expect(recipient_list.reload.recipient_ids).to eq('3,4,5,6')
|
||||
end
|
||||
end
|
||||
|
||||
describe "when edited" do
|
||||
it 'should delete recipient_schedules if a recipient is removed'
|
||||
|
||||
it 'should create recipient_schedules if a recipient is added'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,37 +2,34 @@ require 'rails_helper'
|
|||
|
||||
RSpec.describe RecipientSchedule, type: :model do
|
||||
|
||||
let(:question) { Question.create!(text: 'What is the question?', option1: 'A', option2: 'B', option3: 'C', option4: 'D', option5: 'E')}
|
||||
let(:question_list) { QuestionList.create(name: 'Parent Questions', question_ids: "#{question.id},2,3")}
|
||||
let!(:school) { School.create!(name: 'School') }
|
||||
|
||||
let(:recipient) { Recipient.create!(name: 'Parent', phone: '1112223333') }
|
||||
let(:recipient_list) { RecipientList.create(name: 'Parent List', recipient_ids: recipient.id.to_s)}
|
||||
let!(:recipient) { create_recipients(school, 1).first }
|
||||
let!(:recipient_list) do
|
||||
school.recipient_lists.create!(name: 'Parents', recipient_ids: "#{recipient.id}")
|
||||
end
|
||||
|
||||
let(:schedule) do
|
||||
let!(:questions) { create_questions(3) }
|
||||
let!(:question_list) do
|
||||
QuestionList.create!(name: 'Parent Questions', question_ids: questions.map(&:id).join(','))
|
||||
end
|
||||
|
||||
let!(:schedule) do
|
||||
Schedule.create!(
|
||||
name: 'Parent Schedule',
|
||||
recipient_list_id: recipient_list.id,
|
||||
question_list: question_list,
|
||||
random: false,
|
||||
frequency_hours: 24 * 7
|
||||
)
|
||||
end
|
||||
|
||||
let!(:recipient_schedule) do
|
||||
RecipientSchedule.create!(
|
||||
recipient: recipient,
|
||||
schedule: schedule,
|
||||
upcoming_question_ids: "#{question.id},3",
|
||||
attempted_question_ids: '2',
|
||||
last_attempt_at: 2.weeks.ago,
|
||||
next_attempt_at: 2.weeks.ago + (60 * 60 * schedule.frequency_hours)
|
||||
)
|
||||
end
|
||||
let!(:recipient_schedule) { schedule.recipient_schedules.for(recipient).first }
|
||||
|
||||
let!(:not_ready_recipient_schedule) do
|
||||
RecipientSchedule.create!(
|
||||
recipient: recipient,
|
||||
schedule: schedule,
|
||||
upcoming_question_ids: "#{question.id},3",
|
||||
upcoming_question_ids: '1,3',
|
||||
attempted_question_ids: '2',
|
||||
last_attempt_at: 1.day.ago,
|
||||
next_attempt_at: 1.day.ago + (60 * 60 * schedule.frequency_hours)
|
||||
|
|
@ -50,7 +47,7 @@ RSpec.describe RecipientSchedule, type: :model do
|
|||
|
||||
describe 'next_question' do
|
||||
it 'should provide the next question from the upcoming_question_ids list' do
|
||||
expect(recipient_schedule.next_question).to eq(question)
|
||||
expect(recipient_schedule.next_question).to eq(questions.first)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -66,17 +63,17 @@ RSpec.describe RecipientSchedule, type: :model do
|
|||
expect(attempt.recipient).to eq(recipient)
|
||||
expect(attempt.schedule).to eq(schedule)
|
||||
expect(attempt.recipient_schedule).to eq(recipient_schedule)
|
||||
expect(attempt.question).to eq(question)
|
||||
expect(attempt.question).to eq(questions.first)
|
||||
expect(attempt.sent_at.to_i).to eq(Time.new.to_i)
|
||||
expect(attempt.answer_index).to be_nil
|
||||
end
|
||||
|
||||
it 'should update the upcoming_questions_ids' do
|
||||
expect(recipient_schedule.upcoming_question_ids).to eq('3')
|
||||
expect(recipient_schedule.upcoming_question_ids).to eq(questions[1..2].map(&:id).join(','))
|
||||
end
|
||||
|
||||
it 'should update the attempted_question_ids' do
|
||||
expect(recipient_schedule.attempted_question_ids).to eq("2,#{question.id}")
|
||||
expect(recipient_schedule.attempted_question_ids).to eq(questions.first.id.to_s)
|
||||
end
|
||||
|
||||
it 'should update last_attempt_at' do
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ require 'rails_helper'
|
|||
|
||||
describe Recipient do
|
||||
describe "Import" do
|
||||
|
||||
let(:school) { School.create!(name: 'School') }
|
||||
let(:data) { "name,phone\rJared,111-222-333\rLauren,222-333-4444\rAbby,333-444-5555\r" }
|
||||
let(:file) { instance_double('File', path: 'path') }
|
||||
|
|
@ -15,4 +14,8 @@ describe Recipient do
|
|||
expect(Recipient.all.map(&:school).uniq).to eq([school])
|
||||
end
|
||||
end
|
||||
|
||||
describe "When Deleted" do
|
||||
it 'should delete all recipient_schedules'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,46 +2,61 @@ require 'rails_helper'
|
|||
|
||||
describe Schedule do
|
||||
|
||||
let!(:school) { School.create!(name: 'School') }
|
||||
|
||||
let!(:recipients) { create_recipients(school, 3) }
|
||||
let!(:recipient_list) do
|
||||
school.recipient_lists.create!(name: 'Parents', recipient_ids: recipients.map(&:id).join(','))
|
||||
end
|
||||
|
||||
let!(:kid_recipients) { create_recipients(school, 3) }
|
||||
let!(:kids_recipient_list) do
|
||||
school.recipient_lists.create!(name: 'Kids', recipient_ids: kid_recipients.map(&:id).join(','))
|
||||
end
|
||||
|
||||
let!(:questions) { create_questions(3) }
|
||||
let!(:question_list) do
|
||||
QuestionList.create!(name: 'Questions', question_ids: questions.map(&:id).join(','))
|
||||
end
|
||||
|
||||
let(:default_schedule_params) {
|
||||
{
|
||||
school: school,
|
||||
recipient_list: recipient_list,
|
||||
question_list: question_list,
|
||||
name: 'Parents Schedule',
|
||||
description: 'Schedule for parent questions',
|
||||
start_date: 1.month.ago,
|
||||
end_date: 11.months.from_now,
|
||||
active: true
|
||||
}
|
||||
}
|
||||
|
||||
let!(:active_schedule) do
|
||||
Schedule.create!(default_schedule_params)
|
||||
end
|
||||
|
||||
let!(:active_schedule_kids) do
|
||||
Schedule.create!(default_schedule_params.merge!(name: 'Kids Schedule', recipient_list: kids_recipient_list))
|
||||
end
|
||||
|
||||
let!(:old_schedule) {
|
||||
Schedule.create!(default_schedule_params.merge!(start_date: 13.month.ago, end_date: 1.months.ago))
|
||||
}
|
||||
|
||||
let!(:paused_schedule) {
|
||||
Schedule.create!(default_schedule_params.merge!(active: false))
|
||||
}
|
||||
|
||||
describe "active" do
|
||||
|
||||
let!(:school) { School.create!(name: 'School') }
|
||||
let!(:recipient_list) { RecipientList.create!(name: 'Parents', recipient_id_array: [1, 2, 3]) }
|
||||
let!(:kids_recipient_list) { RecipientList.create!(name: 'Kids', recipient_id_array: [4, 5, 6]) }
|
||||
let!(:question_list) { QuestionList.create!(name: 'Questions', question_id_array: [1, 2, 3]) }
|
||||
|
||||
let(:default_schedule_params) {
|
||||
{
|
||||
school: school,
|
||||
recipient_list: recipient_list,
|
||||
question_list: question_list,
|
||||
name: 'Parents Schedule',
|
||||
description: 'Schedule for parent questions',
|
||||
start_date: 1.month.ago,
|
||||
end_date: 11.months.from_now,
|
||||
active: true
|
||||
}
|
||||
}
|
||||
|
||||
let!(:active_schedule) do
|
||||
Schedule.create!(default_schedule_params)
|
||||
end
|
||||
|
||||
let!(:active_schedule_kids) do
|
||||
Schedule.create!(default_schedule_params.merge!(name: 'Kids Schedule', recipient_list: kids_recipient_list))
|
||||
end
|
||||
|
||||
let!(:old_schedule) {
|
||||
Schedule.create!(default_schedule_params.merge!(start_date: 13.month.ago, end_date: 1.months.ago))
|
||||
}
|
||||
|
||||
let!(:paused_schedule) {
|
||||
Schedule.create!(default_schedule_params.merge!(active: false))
|
||||
}
|
||||
|
||||
it 'finds active schedules' do
|
||||
active = Schedule.active
|
||||
expect(active.length).to eq(2)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
it 'creates a recipient_schedule for every recipient when created' do
|
||||
expect(active_schedule.recipient_schedules.length).to eq(3)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -121,3 +121,29 @@ class FakeSMS
|
|||
self.class.messages << Message.new(from, to, body)
|
||||
end
|
||||
end
|
||||
|
||||
def create_recipients(school, count)
|
||||
recipients = []
|
||||
count.times do |i|
|
||||
recipients << school.recipients.create(
|
||||
name: "Person#{count}",
|
||||
phone: "#{count}" * 10,
|
||||
)
|
||||
end
|
||||
return recipients
|
||||
end
|
||||
|
||||
def create_questions(count)
|
||||
questions = []
|
||||
count.times do |i|
|
||||
questions << Question.create(
|
||||
text: "Question #{i}:#{count}",
|
||||
option1: "Option #{i}:#{count} A",
|
||||
option2: "Option #{i}:#{count} B",
|
||||
option3: "Option #{i}:#{count} C",
|
||||
option4: "Option #{i}:#{count} D",
|
||||
option5: "Option #{i}:#{count} E"
|
||||
)
|
||||
end
|
||||
return questions
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue