From d916687c176ad73c03111ecdd4d483a0465c4072 Mon Sep 17 00:00:00 2001 From: Lori Bailey <44073106+elceebee@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:14:05 +0000 Subject: [PATCH] WIP --- .../withdrawal_reasons_reports_controller.rb | 1 + app/frontend/styles/provider/_all.scss | 1 + .../provider/_withdrawal_reasons_report.scss | 34 +++++ app/models/withdrawal_reason.rb | 14 +- ...ate_withdrawal_reasons_data_by_provider.rb | 130 ++++++++++++++++++ .../withdrawal_reasons_reports/show.html.erb | 39 ++++++ .../reports/withdrawal_reports/index.html.erb | 7 +- .../withdrawal_reasons_report.yml | 11 ++ 8 files changed, 226 insertions(+), 11 deletions(-) create mode 100644 app/frontend/styles/provider/_withdrawal_reasons_report.scss create mode 100644 app/services/provider_interface/candidate_withdrawal_reasons_data_by_provider.rb create mode 100644 config/locales/provider_interface/withdrawal_reasons_report.yml diff --git a/app/controllers/provider_interface/reports/withdrawal_reasons_reports_controller.rb b/app/controllers/provider_interface/reports/withdrawal_reasons_reports_controller.rb index fe2a9022bab..edd3e7e0e58 100644 --- a/app/controllers/provider_interface/reports/withdrawal_reasons_reports_controller.rb +++ b/app/controllers/provider_interface/reports/withdrawal_reasons_reports_controller.rb @@ -5,6 +5,7 @@ class WithdrawalReasonsReportsController < ProviderInterfaceController def show @provider = current_user.providers.find(provider_id) + @withdrawal_reason_report = ProviderInterface::CandidateWithdrawalReasonsDataByProvider.new(@provider) end private diff --git a/app/frontend/styles/provider/_all.scss b/app/frontend/styles/provider/_all.scss index 2c6be65a718..76c65c4e4f2 100644 --- a/app/frontend/styles/provider/_all.scss +++ b/app/frontend/styles/provider/_all.scss @@ -16,3 +16,4 @@ @import "user-card"; @import "email-preview"; @import "recruitment_performance_report"; +@import "withdrawal_reasons_report"; diff --git a/app/frontend/styles/provider/_withdrawal_reasons_report.scss b/app/frontend/styles/provider/_withdrawal_reasons_report.scss new file mode 100644 index 00000000000..937f8c3bf19 --- /dev/null +++ b/app/frontend/styles/provider/_withdrawal_reasons_report.scss @@ -0,0 +1,34 @@ +.withdrawal-reasons-report-table { + &__wrapper { + overflow-x: auto; + } + + &__heading { + border-bottom: none; + } + + &__cell--main-reason { + font-weight: $govuk-font-weight-bold; + + background: govuk-colour("light-grey"); + border-top: 2px solid $govuk-input-border-colour; + } + + &__cell--second-level-reason { + padding-left: govuk-spacing(3); + } + + &__cell--third-level-reason { + padding-left: govuk-spacing(5); + } + + &__cell--second-level-with-nested-reasons { + padding-left: govuk-spacing(3); + + background: govuk-colour("light-grey"); + } + + &__cell--light-grey-background { + background: govuk-colour("light-grey"); + } +} diff --git a/app/models/withdrawal_reason.rb b/app/models/withdrawal_reason.rb index cfcccb4e8b7..9f3d4a8710a 100644 --- a/app/models/withdrawal_reason.rb +++ b/app/models/withdrawal_reason.rb @@ -7,11 +7,7 @@ class WithdrawalReason < ApplicationRecord scope :by_level_one_reason, lambda { |level| keys = get_reason_options(level).map do |key, value| - if value == {} - key - else - value.map { |val_key, _| "#{key}.#{val_key}" } - end + build_reason(key, value) end&.flatten where('reason LIKE ?', "#{level}%").sort do |a, b| @@ -39,4 +35,12 @@ def self.get_reason_options(reason = '') selectable_reasons.dig(*reason.split('.')) end end + + def self.build_reason(key, value) + if value == {} + key + else + value.map { |k, v| build_reason("#{key}.#{k}", v) } + end + end end diff --git a/app/services/provider_interface/candidate_withdrawal_reasons_data_by_provider.rb b/app/services/provider_interface/candidate_withdrawal_reasons_data_by_provider.rb new file mode 100644 index 00000000000..42a9cafd671 --- /dev/null +++ b/app/services/provider_interface/candidate_withdrawal_reasons_data_by_provider.rb @@ -0,0 +1,130 @@ +module ProviderInterface + class CandidateWithdrawalReasonsDataByProvider + def initialize(provider) + @provider = provider + end + + ReasonRow = Struct.new(:reason, :before_accepting, :after_accepting, :total) + + def show_report? + all_rows.any? + end + + def all_rows + return [] if withdrawal_reasons.count < 10 + + rows = [] + nested_reasons.each_key do |level_one_reason| + rows << build_reason_row(level_one_reason, 'level_one') + + nested_reasons[level_one_reason].each_key do |level_two_reason| + full_level_two_reason = [level_one_reason, level_two_reason].join('.') + + if nested_reasons[level_one_reason][level_two_reason].present? + rows << build_reason_row(full_level_two_reason, 'level_two_with_nested_reasons') + nested_reasons[level_one_reason][level_two_reason].each_key do |level_three_reason| + full_level_three_reason = [level_one_reason, level_two_reason, level_three_reason].join('.') + rows << build_reason_row(full_level_three_reason, 'level_three') + end + else + rows << build_reason_row(full_level_two_reason, 'level_two') + end + end + end + rows + end + + private + + def build_reason_row(reason, level) + ReasonRow.new( + reason: { + text: translate(reason), + html_attributes: reason_attributes_for(level), + }, + before_accepting: { + text: before_accepting_count(reason), + html_attributes: numeric_attributes_for(level), + numeric: true, + }, + after_accepting: { + text: after_accepting_count(reason), + html_attributes: numeric_attributes_for(level), + numeric: true, + }, + total: { + text: before_accepting_count(reason) + after_accepting_count(reason), + html_attributes: numeric_attributes_for(level), numeric: true + }, + ) + end + + def reason_attributes_for(level) + case level + when 'level_one' + { class: 'withdrawal-reasons-report-table__cell--main-reason' } + when 'level_two' + { class: 'withdrawal-reasons-report-table__cell--second-level-reason' } + when 'level_two_with_nested_reasons' + { class: 'withdrawal-reasons-report-table__cell--second-level-with-nested-reasons' } + when 'level_three' + { class: 'withdrawal-reasons-report-table__cell--third-level-reason' } + else + {} + end + end + + def numeric_attributes_for(level) + case level + when 'level_one' + { class: 'withdrawal-reasons-report-table__cell--main-reason' } + when 'level_two_with_nested_reasons' + { class: 'withdrawal-reasons-report-table__cell--light-grey-background' } + else + {} + end + end + + def translate(string) + translation_string = string.dup.gsub('-', '_') + I18n.t("candidate_interface.withdrawal_reasons.reasons.#{translation_string}.label") + end + + def before_accepting_count(reason) + withdrawal_reasons_before_acceptance.filter { |r| r.starts_with?(reason) }.length + end + + def after_accepting_count(reason) + withdrawal_reasons_after_acceptance.filter { |r| r.starts_with?(reason) }.length + end + + def nested_reasons + @nested_reasons ||= WithdrawalReason.selectable_reasons + end + + def withdrawal_reasons_before_acceptance + @withdrawal_reasons_before_acceptance ||= + withdrawal_reasons + .where(application_choices: { accepted_at: nil }) + .uniq + .pluck(:reason) + end + + def withdrawal_reasons_after_acceptance + @withdrawal_reasons_after_acceptance ||= + withdrawal_reasons + .where.not(application_choices: { accepted_at: nil }) + .uniq + .pluck(:reason) + end + + def withdrawal_reasons + @withdrawal_reasons ||= + WithdrawalReason + .joins(:application_choice) + .published + .where('application_choices.provider_ids @> ARRAY[?]::bigint[]', @provider.id) + .where(application_choices: { current_recruitment_cycle_year: RecruitmentCycle.current_year }) + end + end +end diff --git a/app/views/provider_interface/reports/withdrawal_reasons_reports/show.html.erb b/app/views/provider_interface/reports/withdrawal_reasons_reports/show.html.erb index dd48b8e9adf..29415e88298 100644 --- a/app/views/provider_interface/reports/withdrawal_reasons_reports/show.html.erb +++ b/app/views/provider_interface/reports/withdrawal_reasons_reports/show.html.erb @@ -8,5 +8,44 @@ <%= @provider.name %> <%= t('page_titles.provider.withdrawal_reasons_report') %> + <% if @withdrawal_reason_report.show_report? %> +

+ <%= t('provider_interface.withdrawal_reasons.show.report_description') %> +

+ <% else %> +

+ <%= t('provider_interface.withdrawal_reasons.show.report_not_visible') %> +

+ <% end %> + + + <% if @withdrawal_reason_report.show_report? %> +
+
+ <%= govuk_table do |table| %> + <%= table.with_caption(text: t('provider_interface.withdrawal_reasons.show.table_caption'), html_attributes: { class: 'govuk-visually-hidden' }) %> + <%= table.with_head do |head| %> + <%= head.with_row do |row| %> + <% %w[withdrawal_reason before_accepting after_accepting total].each do |heading| %> + <%= row.with_cell( + text: t("provider_interface.withdrawal_reasons.show.#{heading}"), + html_attributes: { class: 'withdrawal-reasons-report-table__heading' }, + ) %> + <% end %> + <% end %> + <% end %> + <%= table.with_body do |body| %> + <% @withdrawal_reason_report.all_rows.each do |reason_row| %> + <%= body.with_row do |row| %> + <%= row.with_cell(**reason_row.reason) %> + <%= row.with_cell(**reason_row.before_accepting) %> + <%= row.with_cell(**reason_row.after_accepting) %> + <%= row.with_cell(**reason_row.total) %> + <% end %> + <% end %> + <% end %> + <% end %> + <% end %> +
diff --git a/app/views/provider_interface/reports/withdrawal_reports/index.html.erb b/app/views/provider_interface/reports/withdrawal_reports/index.html.erb index 1b2f8441539..1cd66c18c4e 100644 --- a/app/views/provider_interface/reports/withdrawal_reports/index.html.erb +++ b/app/views/provider_interface/reports/withdrawal_reports/index.html.erb @@ -2,7 +2,6 @@ <%= content_for :before_content, breadcrumbs(t('page_titles.provider.reports') => provider_interface_reports_path, t('page_titles.provider.withdrawal_reports') => nil) %> -

<%= t('page_titles.provider.withdrawal_reports') %>

@@ -27,14 +26,10 @@ <%= govuk_link_to( t('page_titles.provider.withdrawal_reasons_report'), provider_interface_reports_provider_withdrawal_reasons_report_path(provider), - no_visited_state: true + no_visited_state: true, ) %> - <% end %> - - -
diff --git a/config/locales/provider_interface/withdrawal_reasons_report.yml b/config/locales/provider_interface/withdrawal_reasons_report.yml new file mode 100644 index 00000000000..768217780f1 --- /dev/null +++ b/config/locales/provider_interface/withdrawal_reasons_report.yml @@ -0,0 +1,11 @@ +en: + provider_interface: + withdrawal_reasons: + show: + report_description: TBD placeholder text for when the report is visible + report_not_visible: TBD placeholder text for when the report is not visible + table_caption: Withdrawal reason report data + withdrawal_reason: Withdrawal reason + before_accepting: Before accepting + after_accepting: After accepting + total: Total