Skip to content

Commit 3136713

Browse files
committed
New SLA status page within CMS for users with staff management access
1 parent d6a8e0f commit 3136713

File tree

9 files changed

+571
-0
lines changed

9 files changed

+571
-0
lines changed

.rubocop.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ inherit_mode:
1414
Layout/EmptyLineAfterMagicComment:
1515
Enabled: true
1616

17+
Layout/LineLength:
18+
Max: 130
19+
1720
RSpec/AnyInstance:
1821
Enabled: false
1922

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# frozen_string_literal: true
2+
3+
class AssessorInterface::ServiceLevelAgreementsController < AssessorInterface::BaseController
4+
def index
5+
authorize %i[assessor_interface service_level_agreement]
6+
7+
@view_object =
8+
AssessorInterface::ServiceLevelAgreementIndexViewObject.new(params:)
9+
10+
render layout: "full_from_desktop"
11+
end
12+
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# frozen_string_literal: true
2+
3+
class AssessorInterface::ServiceLevelAgreementPolicy < ApplicationPolicy
4+
def index?
5+
user.manage_staff_permission? && !user.archived?
6+
end
7+
end
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# frozen_string_literal: true
2+
3+
class AssessorInterface::ServiceLevelAgreementIndexViewObject
4+
include ActionView::Helpers::FormOptionsHelper
5+
include Pagy::Backend
6+
7+
def initialize(params:)
8+
@params = params
9+
end
10+
11+
def application_forms_pagy
12+
application_forms_with_pagy.first
13+
end
14+
15+
def application_forms_records
16+
application_forms_with_pagy.last
17+
end
18+
19+
def breached_sla_for_starting_prioritisation_checks_count
20+
application_forms_with_prioritisation_checks_not_started.where(
21+
"working_days_between_submitted_and_today > ?",
22+
WORKING_DAYS_TO_START_PRIORITISATION_CHECKS,
23+
).count
24+
end
25+
26+
def nearing_sla_for_starting_prioritisation_checks_count
27+
application_forms_with_prioritisation_checks_not_started.where(
28+
working_days_between_submitted_and_today:
29+
WORKING_DAYS_NEARING_START_PRIORITISATION_CHECKS_DEADLINE..WORKING_DAYS_TO_START_PRIORITISATION_CHECKS,
30+
).count
31+
end
32+
33+
def breached_sla_for_completing_prioritised_applications_count
34+
application_forms_prioritised_but_assessment_not_completed.where(
35+
"working_days_between_submitted_and_today > ?",
36+
WORKING_DAYS_TO_FINISH_ASSESSMENT_FOR_PRIORITISED,
37+
).count
38+
end
39+
40+
def nearing_sla_for_completing_prioritised_applications_count
41+
application_forms_prioritised_but_assessment_not_completed.where(
42+
working_days_between_submitted_and_today:
43+
WORKING_DAYS_NEARING_FINISH_ASSESSMENT_FOR_PRIORITISED_DEADLINE..WORKING_DAYS_TO_FINISH_ASSESSMENT_FOR_PRIORITISED,
44+
).count
45+
end
46+
47+
def sla_start_prioritisation_checks_tag_colour(application_form)
48+
return if application_form.assessment.nil?
49+
50+
if application_form.assessment.started_at.present? ||
51+
application_form.assessment.prioritisation_work_history_checks.empty?
52+
return
53+
end
54+
55+
if application_form.working_days_between_submitted_and_today.to_i >
56+
WORKING_DAYS_TO_START_PRIORITISATION_CHECKS
57+
"red"
58+
elsif application_form.working_days_between_submitted_and_today.to_i >=
59+
WORKING_DAYS_NEARING_START_PRIORITISATION_CHECKS_DEADLINE
60+
"yellow"
61+
else
62+
"green"
63+
end
64+
end
65+
66+
def sla_completed_prioritised_tag_colour(application_form)
67+
return if application_form.assessment.nil?
68+
69+
if !application_form.assessment.prioritised? ||
70+
application_form.assessment.verification_started_at.present?
71+
return
72+
end
73+
74+
if application_form.working_days_between_submitted_and_today.to_i >
75+
WORKING_DAYS_TO_FINISH_ASSESSMENT_FOR_PRIORITISED
76+
"red"
77+
elsif application_form.working_days_between_submitted_and_today.to_i >=
78+
WORKING_DAYS_NEARING_FINISH_ASSESSMENT_FOR_PRIORITISED_DEADLINE
79+
"yellow"
80+
else
81+
"green"
82+
end
83+
end
84+
85+
private
86+
87+
WORKING_DAYS_TO_START_PRIORITISATION_CHECKS = 10
88+
WORKING_DAYS_NEARING_START_PRIORITISATION_CHECKS_DEADLINE = 8
89+
90+
WORKING_DAYS_TO_FINISH_ASSESSMENT_FOR_PRIORITISED = 40
91+
WORKING_DAYS_NEARING_FINISH_ASSESSMENT_FOR_PRIORITISED_DEADLINE = 35
92+
93+
def application_forms_with_pagy
94+
@application_forms_with_pagy ||=
95+
pagy(
96+
application_forms_with_filter.order(
97+
working_days_between_submitted_and_today: :desc,
98+
),
99+
)
100+
end
101+
102+
def application_forms_with_filter
103+
@application_forms_with_filter ||=
104+
if params[:tab] == "40"
105+
application_forms_prioritised_but_assessment_not_completed
106+
else
107+
application_forms_with_prioritisation_checks_not_started
108+
end
109+
end
110+
111+
def application_forms_with_prioritisation_checks_not_started
112+
ApplicationForm
113+
.joins(assessment: :prioritisation_work_history_checks)
114+
.where(assessment: { started_at: nil })
115+
.where.not(assessment: { prioritisation_work_history_checks: nil })
116+
.distinct
117+
end
118+
119+
def application_forms_prioritised_but_assessment_not_completed
120+
ApplicationForm
121+
.joins(:assessment)
122+
.where(assessment: { verification_started_at: nil, prioritised: true })
123+
.distinct
124+
end
125+
126+
attr_reader :params
127+
end
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<% content_for :page_title, "SLA Status" %>
2+
3+
<h1 class="govuk-heading-xl">SLA Status (Prioritisation)</h1>
4+
5+
<div class="govuk-grid-row">
6+
<div class="govuk-grid-column-one-half">
7+
<h3 class="govuk-heading-m">Breached 10 day SLA</h3>
8+
<%= govuk_inset_text { @view_object.breached_sla_for_starting_prioritisation_checks_count.to_s } %>
9+
</div>
10+
<div class="govuk-grid-column-one-half">
11+
<h3 class="govuk-heading-m">Breached 40 day SLA</h3>
12+
<%= govuk_inset_text { @view_object.breached_sla_for_completing_prioritised_applications_count.to_s } %>
13+
</div>
14+
</div>
15+
16+
<div class="govuk-grid-row">
17+
<div class="govuk-grid-column-one-half">
18+
<h3 class="govuk-heading-m">Nearing 10 day SLA</h3>
19+
<%= govuk_inset_text { @view_object.nearing_sla_for_starting_prioritisation_checks_count.to_s } %>
20+
</div>
21+
<div class="govuk-grid-column-one-half">
22+
<h3 class="govuk-heading-m">Nearing 40 day SLA</h3>
23+
<%= govuk_inset_text { @view_object.nearing_sla_for_completing_prioritised_applications_count.to_s } %>
24+
</div>
25+
</div>
26+
27+
<%= govuk_details(summary_text: "SLA definitions") do %>
28+
<p class="govuk-body">10 day SLA relates to application forms that are going through prioritisation checks and expect checks to begin within 10 days of being submitted. For these applications, we consider them as nearing SLA once they are within 2 days of breaching the SLA.</p>
29+
<p class="govuk-body">40 day SLA relates to application forms are prioritised and expect initial assessment to be completed and moved to verification within 40 days of being submitted. For these applications, we consider them as nearing SLA once they are within 5 days of breaching the SLA.</p>
30+
<% end %>
31+
32+
<hr class="govuk-section-break govuk-section-break--m govuk-section-break--visible">
33+
34+
<h2 class="govuk-heading-l">Application forms</h2>
35+
36+
<div class="govuk-tabs" data-module="govuk-tabs">
37+
<h2 class="govuk-tabs__title">
38+
Contents
39+
</h2>
40+
<ul class="govuk-tabs__list">
41+
<li class="govuk-tabs__list-item <%= 'govuk-tabs__list-item--selected' if params[:tab] != "40" %>">
42+
<%= link_to "10 day SLA", assessor_interface_service_level_agreements_path %>
43+
</li>
44+
<li class="govuk-tabs__list-item <%= 'govuk-tabs__list-item--selected' if params[:tab] == "40" %>">
45+
<%= link_to "40 day SLA", assessor_interface_service_level_agreements_path(tab: "40") %>
46+
</li>
47+
</ul>
48+
<div class="govuk-tabs__panel">
49+
<% if (records = @view_object.application_forms_records).present? %>
50+
<%=
51+
govuk_table(classes: "application-forms-sla") do |table|
52+
table.with_head do |head|
53+
head.with_row do |row|
54+
row.with_cell(header: true, text: "Reference")
55+
row.with_cell(header: true, text: "Country/Region")
56+
row.with_cell(header: true, text: "Working days since submission")
57+
end
58+
end
59+
60+
table.with_body do |body|
61+
records.each do |application_form|
62+
body.with_row do |row|
63+
row.with_cell { govuk_link_to application_form.reference, [:assessor_interface, application_form] }
64+
row.with_cell { CountryName.from_region(application_form.region) }
65+
row.with_cell do
66+
if params[:tab] == "40"
67+
govuk_tag(text: application_form.working_days_between_submitted_and_today, colour: @view_object.sla_completed_prioritised_tag_colour(application_form) )
68+
else
69+
govuk_tag(text: application_form.working_days_between_submitted_and_today, colour: @view_object.sla_start_prioritisation_checks_tag_colour(application_form) )
70+
end
71+
end
72+
end
73+
end
74+
end
75+
end
76+
%>
77+
<%= govuk_pagination(pagy: @view_object.application_forms_pagy) %>
78+
<% else %>
79+
<h2 class="govuk-heading-m"><%= t(".results.empty") %></h2>
80+
<% end %>
81+
</div>
82+
</div>
83+

app/views/shared/_header.html.erb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@
3131
href: main_app.assessor_interface_staff_index_path,
3232
active: current_page?(main_app.assessor_interface_staff_index_path)
3333
) %>
34+
<% service_navigation.with_navigation_item(
35+
text: "SLA Status",
36+
href: main_app.assessor_interface_service_level_agreements_path,
37+
active: current_page?(main_app.assessor_interface_service_level_agreements_path)
38+
) %>
3439
<% end %>
3540
<% service_navigation.with_navigation_item(text: "Sign out", href: main_app.destroy_staff_session_path) %>
3641
<% end %>

config/routes.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
namespace :assessor_interface, path: "/assessor" do
1515
root to: redirect("/assessor/applications")
1616

17+
resources :service_level_agreements, only: %i[index]
18+
1719
resources :staff, only: %i[index edit update] do
1820
member do
1921
get "archive", to: "staff#edit_archive"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# frozen_string_literal: true
2+
3+
require "rails_helper"
4+
5+
RSpec.describe AssessorInterface::ServiceLevelAgreementPolicy do
6+
it_behaves_like "a policy"
7+
8+
describe "#index?" do
9+
subject(:index?) { described_class.new(user, nil).index? }
10+
11+
it_behaves_like "a policy method requiring the manage staff permission"
12+
end
13+
end

0 commit comments

Comments
 (0)