Skip to content

Commit

Permalink
Merge pull request #8644 from DFE-Digital/714-manage-instances-of-aut…
Browse files Browse the repository at this point in the history
…omatic-rejections

Manage: Identify and remove all instances of "Automatic Rejections"
  • Loading branch information
zarembas authored Oct 9, 2023
2 parents 7bb08d8 + f33140e commit 913e913
Show file tree
Hide file tree
Showing 19 changed files with 118 additions and 235 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@

<% if @application_choice.continuous_applications? %>

<% unless @application_choice.days_since_submission.nil? %>
<% days_since_submission = @application_choice.days_since_submission %>
<% unless @application_choice.days_since_sent_to_provider.nil? %>
<% days_since_sent_to_provider = @application_choice.days_since_sent_to_provider %>
<p class="govuk-!-margin-top-2">
<% if days_since_submission.zero? %>
<% if days_since_sent_to_provider.zero? %>
Application submitted today.
<% else %>
Application submitted <%= days_since_submission %> <%= 'day'.pluralize(days_since_submission) %> ago.
Application submitted <%= days_since_sent_to_provider %> <%= 'day'.pluralize(days_since_sent_to_provider) %> ago.
<% end %>
</p>
<% end %>
Expand All @@ -31,8 +31,8 @@
<% if @application_choice.inactive? && @application_choice.application_form.can_add_more_choices? %>
You can add an application for a different training provider while you wait for a decision on this application.
<% else %>
If you do not receive a response from this training provider, you can withdraw this application and apply to another provider.
<% end %>
If you do not receive a response from this training provider, you can withdraw this application and apply to another provider.
<% end %>
</p>

<% else %>
Expand All @@ -52,22 +52,22 @@
Your training will now start in <%= (@application_choice.current_course_option.course.start_date + 1.year).to_fs(:month_and_year) %>.
</p>
<% elsif @application_choice.pending_conditions? || @application_choice.recruited? || @application_choice.offer? %>
<%= govuk_details(
<%= govuk_details(
summary_text: "What to do if you’re unable to start training in #{@application_choice.current_course_option.course.start_date.to_fs(:month_and_year)}",
classes: 'govuk-!-margin-bottom-0 govuk-!-margin-top-2',
) do %>
<p>
You can defer your offer and start your course a year later.
</p>
<p>
You can defer your offer and start your course a year later.
</p>

<p>
Contact <%= @application_choice.current_course_option.course.provider.name %> to ask if it’s possible to defer, this will not affect your existing offer.
</p>
<p>
Contact <%= @application_choice.current_course_option.course.provider.name %> to ask if it’s possible to defer, this will not affect your existing offer.
</p>

<p>
<p>
If your provider agrees, you’ll need to accept the offer first.
</p>
</p>

<% end %>
<% end %>
<% end %>
<% end %>
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,7 @@

<div class="govuk-grid-column-one-third">
<dl class="app-application-card__list app-application-card__list--secondary">
<% if days_to_respond_text %>
<dt class="govuk-visually-hidden">Days left to respond</dt>
<dd class="govuk-body-s"><%= days_to_respond_text %></dd>
<% elsif candidate_days_to_respond_text %>
<dt class="govuk-visually-hidden">Days left for candidate to respond</dt>
<dd class="govuk-body-s"><%= candidate_days_to_respond_text %></dd>
<% end %>
<dt class="govuk-visually-hidden">Cycle</dt>
<dd class="govuk-body-s"><%= relative_date_text %></dd>
<dd class="govuk-hint govuk-!-font-size-16"><%= recruitment_cycle_text %></dd>
</dl>
</div>
Expand Down
24 changes: 7 additions & 17 deletions app/components/provider_interface/application_card_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,13 @@ def initialize(application_choice:)
@site_name = application_choice.current_site.name
end

def days_to_respond_text
if (days_left_to_respond = application_choice.days_left_to_respond)
if days_left_to_respond.zero?
'Last day to make decision'
else
"#{days_until(Date.current + days_left_to_respond).capitalize} to make decision"
end
end
end

def candidate_days_to_respond_text
if (days_left_to_respond = application_choice.days_until_decline_by_default)
if days_left_to_respond.positive?
"#{days_until(Date.current + days_left_to_respond).capitalize} for candidate to respond"
else
'Last day for candidate to respond'
end
def relative_date_text
if application_choice.offer?
days = application_choice.days_since_offered
"Offer made #{days_since(days)}"
else
days = application_choice.days_since_sent_to_provider
"Received #{days_since(days)}"
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@ module ProviderInterface
module ApplicationHeaderComponents
class OfferWillBeDeclinedByDefaultComponent < ApplicationChoiceHeaderComponent
def continuous_applications_offer_text
time_since_offer = days_from_now.zero? ? 'today' : "#{pluralize(days_from_now, 'day')} ago"
days = application_choice.days_since_offered

"You made this offer #{time_since_offer}. Most candidates respond to offers within 15 working days. The candidate will receive reminders to respond."
end

def days_from_now
(Time.zone.now.beginning_of_day - application_choice.offered_at.beginning_of_day).to_i / 1.day
"You made this offer #{days_since(days)}. Most candidates respond to offers within 15 working days. The candidate will receive reminders to respond."
end

def decline_by_default_text
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@
<% end -%>
</h2>
<p class="govuk-body">
<% if time_is_today_or_tomorrow?(application_choice.reject_by_default_at) -%>
This application will be automatically rejected if a decision has not been made by the end of <%= date_and_time_today_or_tomorrow(application_choice.reject_by_default_at) %>.
<% else -%>
This application will be automatically rejected if a decision has not been made within <%= days_until(application_choice.reject_by_default_at.to_date) %> (<%= application_choice.reject_by_default_at.to_fs(:govuk_date_and_time) %>).
<% end -%>
This application was received <%= days_since(application_choice.days_since_sent_to_provider) %>. You should try and respond to the candidate within 30 days.
</p>

<div class="govuk-button-group">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,7 @@
</div>
<% end %>

<%= f.govuk_date_field(
:date,
hint: {
text: t(
'helpers.hint.provider_interface_interview_wizard.date',
rbd_date: application_choice.reject_by_default_at.to_fs(:govuk_date),
example_date: example_date,
),
},
) %>
<%= f.govuk_date_field(:date, hint: { text: t('helpers.hint.provider_interface_interview_wizard.date', example_date:) }) %>

<%= f.govuk_text_field :time, width: 5, label: { size: 'm' } %>

Expand Down
9 changes: 0 additions & 9 deletions app/forms/provider_interface/interview_wizard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ class InterviewWizard
validate :date_in_future, if: %i[date]
validate :date_and_time_in_future, if: %i[date_and_time],
unless: ->(c) { %i[date time].any? { |d| c.errors.attribute_names.include?(d) } }
validate :date_after_rbd_date, if: %i[date]
validates :provider_id, presence: true, if: %i[application_choice provider_user multiple_application_providers?]
validates :location, presence: true, word_count: { maximum: 2000 }
validates :additional_details, word_count: { maximum: 2000 }
Expand Down Expand Up @@ -84,14 +83,6 @@ def date_in_future
errors.add(:date, :past) if date.is_a?(Date) && date.past?
end

def date_after_rbd_date
rbd_date = application_choice&.reject_by_default_at

if rbd_date.present? && date.is_a?(Date) && date > rbd_date
errors.add(:date, :after_rdb, rbd_date: rbd_date.to_fs(:govuk_date))
end
end

def parsed_time
Timeliness.parse(time)
end
Expand Down
2 changes: 1 addition & 1 deletion app/helpers/task_view_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ def task_view_header(choice)
when 1 then 'Confirm deferred offers'
when 2 then 'Deadline approaching: make decision about application'
when 3 then 'Give feedback: you did not make a decision in time'
when 4 then 'Ready for review'
when 4 then 'Received – make a decision'
when 5 then 'Interviewing'
when 6 then 'Offers pending conditions (previous cycle)'
when 7 then 'Waiting for candidate to respond to offer'
Expand Down
10 changes: 10 additions & 0 deletions app/helpers/view_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,16 @@ def days_until(date)
end
end

def days_since(days)
return unless days.is_a?(Integer)

if days.zero?
'today'
else
"#{pluralize(days, 'day')} ago"
end
end

def boolean_to_word(boolean)
return nil if boolean.nil?

Expand Down
8 changes: 2 additions & 6 deletions app/models/application_choice.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class ApplicationChoice < ApplicationRecord
include Chased
include TouchApplicationFormState
include Dateable

before_create :set_initial_status

Expand Down Expand Up @@ -29,6 +30,7 @@ class ApplicationChoice < ApplicationRecord

has_associated_audits
audited associated_with: :application_form
dateable :sent_to_provider, :offered

# Note that prior to October 2020, we used to have awaiting_references and
# application_complete statuses. These will still show up in older audit logs.
Expand Down Expand Up @@ -255,12 +257,6 @@ def science_gcse_needed?
course.primary_course?
end

def days_since_submission
return if sent_to_provider_at.nil?

(Time.zone.now.to_date - sent_to_provider_at.to_date).to_i
end

private

def set_initial_status
Expand Down
28 changes: 28 additions & 0 deletions app/models/concerns/dateable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# When included in a model, it will create a method for each date field passed in that returns the number of days since
# the date field was set.

# For example, if you have a model with a field called `submitted_at`, you can call `days_since_submitted` on an
# instance of that model

# If you want to add a date field to a model, you can do so like this:
# class MyModel < ApplicationRecord
# dateable :submitted_at, :updated_at
# end

module Dateable
extend ActiveSupport::Concern

included do
def self.dateable(*date_fields)
date_fields.each do |date_field|
field_name = "#{date_field}_at"

define_method("days_since_#{date_field}") do
return unless send(field_name)

(Time.zone.now.beginning_of_day - send(field_name).beginning_of_day).to_i / 1.day
end
end
end
end
end
4 changes: 1 addition & 3 deletions config/locales/provider_interface/interviews.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ en:
additional_details: Additional details
hint:
provider_interface_interview_wizard:
date: No later than %{rbd_date}, after which the application will be automatically rejected - enter numbers, for example, %{example_date}
date: For example, %{example_date}
time: For example, 2pm or 14:30
legend:
provider_interface_interview_wizard:
Expand All @@ -54,9 +54,7 @@ en:
attributes:
date:
past: Interview date must be today or in the future
after_rdb: Interview date must be no later than %{rbd_date}
invalid_date: Interview date must be a real date
blank_date_fields: Interview date must include a %{fields}
blank_date: Enter interview date
time:
invalid: Enter an interview time in the correct format
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,97 +151,6 @@
end
end

describe '#days_to_respond_text' do
let(:application_choice) do
create(
:application_choice,
:awaiting_provider_decision,
)
end

before { application_choice.reject_by_default_at = rbd }

subject(:days_to_respond_text) do
described_class.new(application_choice:).days_to_respond_text
end

context 'when application status is not awaiting_provider_decision' do
let(:rbd) { Time.zone.now }

before { application_choice.status = 'offer' }

it { is_expected.to be_nil }
end

context 'when reject_by_default_at is in the past' do
let(:rbd) { 1.day.ago }

it { is_expected.to be_nil }
end

context 'when less than a day is left to respond' do
let(:rbd) { 1.hour.from_now }

it { is_expected.to eq('Last day to make decision') }
end

context 'when 1 day is left to respond' do
let(:rbd) { 1.day.from_now.end_of_day }

it { is_expected.to eq('1 day to make decision') }
end

context 'when 2 days are left to respond' do
let(:rbd) { 2.days.from_now.end_of_day }

it { is_expected.to eq('2 days to make decision') }
end
end

describe '#decision_by_date_text' do
around do |example|
travel_temporarily_to(Time.zone.local(2020, 6, 1, 12, 30, 0)) { example.run }
end

let(:application_choice) do
create(
:application_choice,
:offered,
decline_by_default_at: dbd,
)
end

before { application_choice.decline_by_default_at = dbd }

subject(:candidate_days_to_respond_text) do
described_class.new(application_choice:).candidate_days_to_respond_text
end

context 'when decision_by_date is in the past' do
let(:dbd) { Time.zone.parse('2020-05-02T09:05:00+01:00') }

it { is_expected.to be_nil }
end

context 'when less than a day is left to respond' do
let(:dbd) { Time.zone.parse('2020-06-02T09:05:00+01:00') }

it { is_expected.to eq('Last day for candidate to respond') }
end

context 'when 1 day is left to respond' do
let(:dbd) { Time.zone.parse('2020-06-03T09:05:00+01:00') }

it { is_expected.to eq('1 day for candidate to respond') }
end

context 'when 2 days are left to respond' do
let(:dbd) { Time.zone.parse('2020-06-04T09:05:00+01:00') }

it { is_expected.to eq('2 days for candidate to respond') }
end
end

describe '#recruitment_cycle_text' do
let(:current_year) { RecruitmentCycle.current_year }

Expand Down
Loading

0 comments on commit 913e913

Please sign in to comment.