Skip to content

Commit

Permalink
Replace usage of single session date
Browse files Browse the repository at this point in the history
Sessions no longer have a single date, instead they can run over
multiple dates. This change supports the underyling database change,
while maintaining the current functionality.

Further work will be required to update the UI to allow the user to pick
multiple dates, updating consent to handle multiple session dates, and
updating the reminder and other emails.
  • Loading branch information
thomasleese committed Sep 25, 2024
1 parent c3b099b commit 7fde834
Show file tree
Hide file tree
Showing 17 changed files with 110 additions and 53 deletions.
4 changes: 2 additions & 2 deletions app/components/app_session_summary_card_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
end

summary_list.with_row do |row|
row.with_key { "Date" }
row.with_value { date }
row.with_key { "Dates" }
row.with_value { dates }
end

summary_list.with_row do |row|
Expand Down
6 changes: 3 additions & 3 deletions app/components/app_session_summary_card_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ def vaccines
@session.programmes.map(&:name)
end

def date
@session.date.to_fs(:long_day_of_week)
def dates
safe_join(@session.dates.map { _1.value.to_fs(:long_day_of_week) }, tag.br)
end

def time
Expand All @@ -42,7 +42,7 @@ def consent_reminders
def deadline_for_responses
return nil if @session.close_consent_at.blank?

if @session.date == @session.close_consent_at
if @session.dates.map(&:value).min == @session.close_consent_at
"Allow responses until the day of the session"
else
close_consent_at = @session.close_consent_at.to_fs(:long_day_of_week)
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/vaccination_records_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ def vaccination_records
:programme,
:vaccine,
patient: [:cohort, :school, { parent_relationships: :parent }],
session: :location
session: %i[dates location]
)
.where(programme:)
.order(:recorded_at)
.strict_loading
# .strict_loading # TODO: Once we move Session#set_timeline_attributes this can be uncommented.
end

def dps_export
Expand Down
6 changes: 4 additions & 2 deletions app/lib/govuk_notify_personalisation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,13 @@ def reason_for_refusal
end

def session_date
session.date.to_fs(:short_day_of_week)
# TODO: Handle multiple dates.
session.dates.map(&:value).min.to_fs(:short_day_of_week)
end

def session_short_date
session.date.to_fs(:short)
# TODO: Handle multiple dates.
session.dates.map(&:value).min.to_fs(:short)
end

def short_patient_name
Expand Down
35 changes: 25 additions & 10 deletions app/models/immunisation_import_row.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,32 @@ def session
return unless valid?

@session ||=
Session
.create_with(active: false)
.find_or_create_by!(
team:,
date: session_date,
location:,
time_of_day: :all_day
)
.tap do
_1.programmes << @programme unless _1.programmes.include?(@programme)
if (
session =
Session.for_date(session_date).find_by(
team:,
location:,
time_of_day: :all_day
)
)
unless session.programmes.include?(@programme)
session.programmes << @programme
end
session
else
ActiveRecord::Base.transaction do
session =
Session.create!(
active: false,
team:,
location:,
time_of_day: :all_day
)
session.dates.create!(value: session_date)
session.programmes << @programme
session
end
end
end

def patient_session
Expand Down
53 changes: 43 additions & 10 deletions app/models/session.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class Session < ApplicationRecord

DEFAULT_DAYS_FOR_REMINDER = 2

attr_accessor :reminder_days_after,
attr_accessor :date,
:reminder_days_after,
:reminder_days_after_custom,
:close_consent_on

Expand All @@ -51,10 +52,21 @@ class Session < ApplicationRecord

enum :time_of_day, %w[morning afternoon all_day], validate: { if: :active? }

scope :past, -> { where(date: ..Time.zone.yesterday) }
scope :in_progress, -> { where(date: Time.zone.today) }
scope :future, -> { where(date: Time.zone.tomorrow..) }
scope :tomorrow, -> { where(date: Time.zone.tomorrow) }
scope :for_date,
->(value) do
where(
SessionDate
.where("session_id = sessions.id")
.where(value:)
.arel
.exists
)
end

scope :past, -> { for_date(..Time.zone.yesterday) }
scope :in_progress, -> { for_date(Time.zone.today) }
scope :future, -> { for_date(Time.zone.tomorrow..) }
scope :tomorrow, -> { for_date(Time.zone.tomorrow) }

scope :send_consent_requests_today,
-> { active.where(send_consent_requests_at: Time.zone.today) }
Expand All @@ -64,6 +76,8 @@ class Session < ApplicationRecord
after_initialize :set_timeline_attributes
after_validation :set_timeline_timestamps

after_save :ensure_session_date_exists

validate :programmes_part_of_team

on_wizard_step :location, exact: true do
Expand All @@ -85,7 +99,9 @@ class Session < ApplicationRecord
presence: true,
comparison: {
greater_than_or_equal_to: -> { Time.zone.today },
less_than_or_equal_to: ->(object) { object.date }
less_than_or_equal_to: ->(object) do
object.dates.map(&:value).min
end
}

validates :reminder_days_after, inclusion: { in: %w[default custom] }
Expand All @@ -104,15 +120,15 @@ class Session < ApplicationRecord
end

def in_progress?
date.to_date == Time.zone.today
dates.map(&:value).include?(Date.current)
end

def wizard_steps
%i[location when cohort timeline confirm]
end

def days_between_consent_and_session
(date - send_consent_requests_at).to_i
(dates.map(&:value).min - send_consent_requests_at).to_i
end

def days_between_consent_and_reminder
Expand Down Expand Up @@ -147,7 +163,8 @@ def set_timeline_attributes
end

unless close_consent_at.nil?
self.close_consent_on = close_consent_at == date ? "default" : "custom"
self.close_consent_on =
close_consent_at == dates.map(&:value).min ? "default" : "custom"
end
end

Expand All @@ -163,10 +180,26 @@ def set_timeline_timestamps
end
)
close_consent_on =
self.close_consent_on == "default" ? date : close_consent_at
(
if self.close_consent_on == "default"
dates.map(&:value).min
else
close_consent_at
end
)

self.send_consent_reminders_at =
send_consent_requests_at + reminder_days_after.days
self.close_consent_at = close_consent_on
end

def ensure_session_date_exists
return if date.nil?

# TODO: Replace with UI to add/remove dates.
ActiveRecord::Base.transaction do
dates.delete_all
dates.create!(value: date)
end
end
end
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<% title = t("consent_forms.confirmation_agreed.title.#{@consent_form.programme.type}",
full_name: @consent_form.full_name,
date: @session.date.to_fs(:long)) %>
date: @session.dates.map(&:value).min.to_fs(:long)) %>
<% # TODO: Handle multiple dates. %>
<% content_for :page_title, title %>
<%= govuk_panel(title_text: title, classes: "app-panel nhsuk-u-margin-bottom-6") %>
6 changes: 3 additions & 3 deletions app/views/programmes/sessions.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<%= govuk_table(html_attributes: { class: "nhsuk-table-responsive" }) do |table| %>
<% table.with_head do |head| %>
<% head.with_row do |row| %>
<% row.with_cell(text: "Date") %>
<% row.with_cell(text: "Dates") %>
<% row.with_cell(text: "Time") %>
<% row.with_cell(text: "Location") %>
<% row.with_cell(text: "Consent period") %>
Expand All @@ -32,8 +32,8 @@
<% sessions.each do |session| %>
<% body.with_row do |row| %>
<% row.with_cell do %>
<span class="nhsuk-table-responsive__heading">Date</span>
<%= session.date.to_fs(:long) %>
<span class="nhsuk-table-responsive__heading">Dates</span>
<%= safe_join(session.dates.map { _1.value.to_fs(:long) }, tag.br) %>
<% end %>
<% row.with_cell do %>
<span class="nhsuk-table-responsive__heading">Time</span>
Expand Down
2 changes: 1 addition & 1 deletion app/views/sessions/edit/timeline.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<span class="nhsuk-visually-hidden">Information: </span>

<p>
Session scheduled for <%= @session.date.to_fs(:long_day_of_week) %> (<%= @session.human_enum_name(:time_of_day) %>)
First session scheduled for <%= @session.dates.map(&:value).min.to_fs(:long_day_of_week) %> (<%= @session.human_enum_name(:time_of_day) %>)
</p>
<% end %>
Expand Down
10 changes: 1 addition & 9 deletions app/views/sessions/show.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
<% page_title = session_location(@session) %>
<% content_for :before_main do %>
<%= render AppBreadcrumbComponent.new(items: [
{ text: "Home", href: dashboard_path },
Expand All @@ -8,13 +6,7 @@
]) %>
<% end %>
<%= h1 page_title: do %>
<%= page_title %>
<span class="nhsuk-caption-l nhsuk-u-margin-top-2">
<%= @session.date.to_fs(:long) %> (<%= @session.human_enum_name(:time_of_day) %>) ·
<%= t("children", count: @patient_sessions.size) %> in cohort
</span>
<% end %>
<%= h1 session_location(@session) %>

<p class="nhsuk-body nhsuk-u-margin-bottom-7">
<%= govuk_tag(text: "In progress", colour: "blue", classes: "nhsuk-u-margin-right-3") %>
Expand Down
10 changes: 9 additions & 1 deletion spec/factories/sessions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
#
FactoryBot.define do
factory :session do
transient { programme { association :programme } }
transient do
date { Date.current }
programme { association :programme }
end

programmes { [programme] }
team { programmes.first&.team || association(:team) }
Expand All @@ -39,6 +42,11 @@

active { true }

after(:create) do |session, evaluator|
next if (date = evaluator.date).nil?
create(:session_date, session:, value: date)
end

trait :draft do
active { false }
end
Expand Down
2 changes: 1 addition & 1 deletion spec/features/e2e_journey_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def and_enter_timelines_and_confirm_the_session_details
expect(page).to have_content(
"Deadline for responsesAllow responses until the day of the session"
)
expect(page).to have_content("DateFriday 1 March 2024")
expect(page).to have_content("DatesFriday 1 March 2024")

click_on "Confirm"
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def and_an_existing_patient_record_exists
create(
:vaccination_record,
programme: @programme,
administered_at: @session.date.in_time_zone + 12.hours,
administered_at: @session.dates.first.value.in_time_zone + 12.hours,
notes: "Foo",
recorded_at: Time.zone.yesterday,
batch: @batch,
Expand Down
2 changes: 1 addition & 1 deletion spec/features/self_consent_gillick_competent_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def given_an_hpv_programme_is_underway
end

def and_it_is_the_day_of_a_vaccination_session
travel_to(@session.date)
travel_to(@session.dates.first.value)
end

def and_there_is_a_child_without_parental_consent
Expand Down
2 changes: 1 addition & 1 deletion spec/features/self_consent_not_gillick_competent_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def given_an_hpv_programme_is_underway
end

def and_it_is_the_day_of_a_vaccination_session
travel_to(@session.date)
travel_to(@session.dates.first.value)
end

def and_there_is_a_child_without_parental_consent
Expand Down
10 changes: 6 additions & 4 deletions spec/mailers/consent_mailer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@

let(:patient) { create(:patient) }
let(:parent) { patient.parents.first }
let(:session) { create(:session, patients: [patient]) }
let(:date) { Date.current }
let(:session) { create(:session, date:, patients: [patient]) }

it { should have_attributes(to: [parent.email]) }

Expand All @@ -76,8 +77,8 @@
mail.message.header["personalisation"].unparsed_value
end

it { should include(session_date: session.date.strftime("%A %-d %B")) }
it { should include(session_short_date: session.date.strftime("%-d %B")) }
it { should include(session_date: date.strftime("%A %-d %B")) }
it { should include(session_short_date: date.strftime("%-d %B")) }

it do
expect(personalisation).to include(
Expand Down Expand Up @@ -105,6 +106,7 @@

let(:patient) { create(:patient) }
let(:parent) { patient.parents.first }
let(:date) { Date.current }
let(:session) { create(:session, patients: [patient]) }

it { should have_attributes(to: [parent.email]) }
Expand All @@ -114,7 +116,7 @@
mail.message.header["personalisation"].unparsed_value
end

it { should include(session_date: session.date.strftime("%A %-d %B")) }
it { should include(session_date: date.strftime("%A %-d %B")) }

it do
expect(personalisation).to include(
Expand Down
4 changes: 3 additions & 1 deletion spec/models/immunisation_import_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@
expect(immunisation_import.sessions.count).to eq(1)

session = immunisation_import.sessions.first
expect(session.date).to eq(Date.new(2024, 5, 14))
expect(session.dates.map(&:value)).to contain_exactly(
Date.new(2024, 5, 14)
)
expect(session.time_of_day).to eq("all_day")
end
end
Expand Down

0 comments on commit 7fde834

Please sign in to comment.