diff --git a/.github/workflows/continuous-integration-terraform.yml b/.github/workflows/continuous-integration-terraform.yml index 2c9ddb6fb..341dc6e7b 100644 --- a/.github/workflows/continuous-integration-terraform.yml +++ b/.github/workflows/continuous-integration-terraform.yml @@ -40,19 +40,19 @@ jobs: run: rm ./terraform/backend.tf - name: Run a Terraform init - uses: docker://hashicorp/terraform:1.8.5 + uses: docker://hashicorp/terraform:1.9.0 with: entrypoint: terraform args: -chdir=terraform init - name: Run a Terraform validate - uses: docker://hashicorp/terraform:1.8.5 + uses: docker://hashicorp/terraform:1.9.0 with: entrypoint: terraform args: -chdir=terraform validate - name: Run a Terraform format check - uses: docker://hashicorp/terraform:1.8.5 + uses: docker://hashicorp/terraform:1.9.0 with: entrypoint: terraform args: -chdir=terraform fmt -check=true -diff=true diff --git a/CHANGELOG.md b/CHANGELOG.md index 12e113b45..836ce7181 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added - Add the date an academy opened to the Grant management export for conversions +- Add the team a project is assigned to to the RPA, SUG and FA letters export + +### Changed + +- The RPA, SUG and FA letter export does not include conversion projects with a + revoked DAO. +- The by month exports do not include conversion projects with a revoked DAO. +- The single by month view and export are now sorted by the conversion or + transfer date only. +- The pre conversion grants export includes a new column that shows the DAO + revocation state of a project as applicable. +- Conversion projects with a DAO (Directive Academy Order) can now be 'revoked' + from the task list. +- DAO revocation is a stepped process which requires at least one reason, + minister name and date of decision. +- Revoking DAO ends a project ## [Release-76][release-76] diff --git a/app/controllers/all/by_month/conversions/projects_controller.rb b/app/controllers/all/by_month/conversions/projects_controller.rb index 8d57f986f..43a10fa97 100644 --- a/app/controllers/all/by_month/conversions/projects_controller.rb +++ b/app/controllers/all/by_month/conversions/projects_controller.rb @@ -48,7 +48,7 @@ def single_month @year = year @date = "#{year}-#{month}-1" - @pager, @projects = pagy_array(ByMonthProjectFetcherService.new.conversion_projects_by_date(month, year)) + @pager, @projects = pagy_array(ByMonthProjectFetcherService.new.conversion_projects_by_date_range(@date, @date)) end private def redirect_if_dates_incorrect diff --git a/app/controllers/all/by_month/transfers/projects_controller.rb b/app/controllers/all/by_month/transfers/projects_controller.rb index d350808dc..130d0bac5 100644 --- a/app/controllers/all/by_month/transfers/projects_controller.rb +++ b/app/controllers/all/by_month/transfers/projects_controller.rb @@ -48,7 +48,7 @@ def single_month @year = year @date = "#{year}-#{month}-1" - @pager, @projects = pagy_array(ByMonthProjectFetcherService.new.transfer_projects_by_date(month, year)) + @pager, @projects = pagy_array(ByMonthProjectFetcherService.new.transfer_projects_by_date_range(@date, @date)) end private def redirect_if_dates_incorrect diff --git a/app/controllers/all/export/by_significant_date/conversions/all_data/projects_controller.rb b/app/controllers/all/export/by_significant_date/conversions/all_data/projects_controller.rb index ffbf7b690..b98d68f26 100644 --- a/app/controllers/all/export/by_significant_date/conversions/all_data/projects_controller.rb +++ b/app/controllers/all/export/by_significant_date/conversions/all_data/projects_controller.rb @@ -1,30 +1,30 @@ class All::Export::BySignificantDate::Conversions::AllData::ProjectsController < ApplicationController + include DateRangable + def date_range_csv authorize Project, :index? - from_date = "#{params[:from_year]}-#{params[:from_month]}-1" - to_date = "#{params[:to_year]}-#{params[:to_month]}-1" - return redirect_if_dates_incorrect if Date.parse(to_date) < Date.parse(from_date) + return redirect_if_dates_incorrect if @to_date < @from_date - projects = ByMonthProjectFetcherService.new.conversion_projects_by_date_range(from_date, to_date) - csv = Export::Conversions::AllDataCsvExportService.new(projects).call + csv = create_csv - send_data csv, filename: "#{from_date}-#{to_date}_schools_due_to_convert.csv", type: :csv, disposition: "attachment" + send_data csv, filename: "#{@from_date}-#{@to_date}_schools_due_to_convert.csv", type: :csv, disposition: "attachment" end def single_month_csv authorize Project, :index? - month = params[:month] - year = params[:year] - - projects = ByMonthProjectFetcherService.new.conversion_projects_by_date(month, year) - csv = Export::Conversions::AllDataCsvExportService.new(projects).call + csv = create_csv - send_data csv, filename: "#{month}-#{year}_schools_due_to_convert.csv", type: :csv, disposition: "attachment" + send_data csv, filename: "#{@from_date.month}-#{@from_date.year}_schools_due_to_convert.csv", type: :csv, disposition: "attachment" end private def redirect_if_dates_incorrect redirect_to date_range_this_month_all_by_month_conversions_projects_path, alert: I18n.t("project.date_range.date_form.from_date_before_to_date") end + + private def create_csv + projects = ByMonthProjectFetcherService.new.conversion_projects_by_date_range(@from_date.to_s, @to_date.to_s) + Export::Conversions::AllDataCsvExportService.new(projects).call + end end diff --git a/app/controllers/all/export/by_significant_date/transfers/all_data/projects_controller.rb b/app/controllers/all/export/by_significant_date/transfers/all_data/projects_controller.rb index e4b9abdec..12af5f078 100644 --- a/app/controllers/all/export/by_significant_date/transfers/all_data/projects_controller.rb +++ b/app/controllers/all/export/by_significant_date/transfers/all_data/projects_controller.rb @@ -1,27 +1,24 @@ class All::Export::BySignificantDate::Transfers::AllData::ProjectsController < ApplicationController + include DateRangable + def date_range_csv authorize Project, :index? - from_date = "#{params[:from_year]}-#{params[:from_month]}-1" - to_date = "#{params[:to_year]}-#{params[:to_month]}-1" - return redirect_if_dates_incorrect if Date.parse(to_date) < Date.parse(from_date) + return redirect_if_dates_incorrect if @to_date < @from_date - projects = ByMonthProjectFetcherService.new.transfer_projects_by_date_range(from_date, to_date) + projects = ByMonthProjectFetcherService.new.transfer_projects_by_date_range(@from_date.to_s, @to_date.to_s) csv = Export::Transfers::AllDataCsvExportService.new(projects).call - send_data csv, filename: "#{from_date}-#{to_date}_academies_due_to_transfer.csv", type: :csv, disposition: "attachment" + send_data csv, filename: "#{@from_date}-#{@to_date}_academies_due_to_transfer.csv", type: :csv, disposition: "attachment" end def single_month_csv authorize Project, :index? - month = params[:month] - year = params[:year] - - projects = ByMonthProjectFetcherService.new.transfer_projects_by_date(month, year) + projects = ByMonthProjectFetcherService.new.transfer_projects_by_date_range(@from_date.to_s, @to_date.to_s) csv = Export::Transfers::AllDataCsvExportService.new(projects).call - send_data csv, filename: "#{month}-#{year}_academies_due_to_transfer.csv", type: :csv, disposition: "attachment" + send_data csv, filename: "#{@from_date.month}-#{@from_date.year}_academies_due_to_transfer.csv", type: :csv, disposition: "attachment" end private def redirect_if_dates_incorrect diff --git a/app/controllers/concerns/date_rangable.rb b/app/controllers/concerns/date_rangable.rb new file mode 100644 index 000000000..c67b938c7 --- /dev/null +++ b/app/controllers/concerns/date_rangable.rb @@ -0,0 +1,28 @@ +module DateRangable + extend ActiveSupport::Concern + + included do + before_action :set_from_and_to_date + end + + private def set_from_and_to_date + if ranged_params? + from_year = params[:from_year] + from_month = params[:from_month] + to_year = params[:to_year] + to_month = params[:to_month] + else + from_year = params[:year] + from_month = params[:month] + to_year = params[:year] + to_month = params[:month] + end + + @from_date = Date.new(from_year.to_i, from_month.to_i).at_beginning_of_month + @to_date = Date.new(to_year.to_i, to_month.to_i).at_end_of_month + end + + private def ranged_params? + params[:from_year].present? && params[:from_month].present? && params[:to_year].present? && params[:to_month].present? + end +end diff --git a/app/controllers/dao_revocations_controller.rb b/app/controllers/dao_revocations_controller.rb index 2aea594df..a4791b360 100644 --- a/app/controllers/dao_revocations_controller.rb +++ b/app/controllers/dao_revocations_controller.rb @@ -1,6 +1,7 @@ class DaoRevocationsController < ApplicationController include Projectable + before_action :redirect_if_not_revokable before_action :redirect_if_project_revoked before_action :redirect_if_invalid_step, only: %i[step update_step change_step update_change_step] @@ -122,6 +123,10 @@ def save project_dao_revocation_step_path(@project, steps[next_index]) end + private def redirect_if_not_revokable + redirect_to project_path(@project), notice: I18n.t("dao_revocations.project_not_revokable") unless @project.dao_revokable? + end + private def redirect_if_project_revoked redirect_to project_path(@project) if @project.dao_revocation.present? end diff --git a/app/forms/export/new_rpa_sug_and_fa_letters_form.rb b/app/forms/export/new_rpa_sug_and_fa_letters_form.rb index a652e34da..33eb2f42b 100644 --- a/app/forms/export/new_rpa_sug_and_fa_letters_form.rb +++ b/app/forms/export/new_rpa_sug_and_fa_letters_form.rb @@ -1,6 +1,6 @@ class Export::NewRpaSugAndFaLettersForm < Export::BaseForm def export - projects = Project.conversions.significant_date_in_range(from_date.to_s, to_date.to_s) + projects = Project.active.or(Project.completed).conversions.significant_date_in_range(from_date.to_s, to_date.to_s) pre_fetched_projects = AcademiesApiPreFetcherService.new.call!(projects) Export::Conversions::RpaSugAndFaLettersCsvExportService.new(pre_fetched_projects).call diff --git a/app/models/project.rb b/app/models/project.rb index ed35b8262..3561884eb 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -43,7 +43,7 @@ class Project < ApplicationRecord scope :transfers, -> { where(type: "Transfer::Project") } scope :ordered_by_completed_date, -> { completed.order(completed_at: :desc) } - scope :in_progress, -> { where(state: 0).assigned } + scope :in_progress, -> { where(state: :active).assigned } scope :assigned, -> { where.not(assigned_to: nil) } scope :assigned_to_caseworker, ->(user) { where(assigned_to: user).or(where(caseworker: user)) } diff --git a/app/presenters/export/csv/project_presenter.rb b/app/presenters/export/csv/project_presenter.rb index db33d3cf5..1f0bd8d55 100644 --- a/app/presenters/export/csv/project_presenter.rb +++ b/app/presenters/export/csv/project_presenter.rb @@ -332,6 +332,16 @@ def declaration_of_expenditure_certificate_date_received @project.tasks_data.declaration_of_expenditure_certificate_date_received.to_fs(:csv) end + def dao_revoked + return I18n.t("export.csv.project.values.not_applicable") unless @project.dao_revokable? + + if @project.dao_revoked? + @project.dao_revocation.date_of_decision.to_fs(:csv) + else + I18n.t("export.csv.project.values.no") + end + end + private def other_contact @contacts_fetcher.other_contact end diff --git a/app/services/by_month_project_fetcher_service.rb b/app/services/by_month_project_fetcher_service.rb index 6889461f5..b482e6b95 100644 --- a/app/services/by_month_project_fetcher_service.rb +++ b/app/services/by_month_project_fetcher_service.rb @@ -4,32 +4,14 @@ def initialize(pre_fetch_academies_api: true) end def conversion_projects_by_date_range(from_date, to_date) - projects = Project.conversions.in_progress.confirmed.significant_date_in_range(from_date, to_date) + projects = Project.active.conversions.in_progress.confirmed.significant_date_in_range(from_date, to_date) AcademiesApiPreFetcherService.new.call!(projects) if @pre_fetch_academies_api end def transfer_projects_by_date_range(from_date, to_date) - projects = Project.transfers.in_progress.confirmed.significant_date_in_range(from_date, to_date) + projects = Project.active.transfers.in_progress.confirmed.significant_date_in_range(from_date, to_date) AcademiesApiPreFetcherService.new.call!(projects) if @pre_fetch_academies_api end - - def conversion_projects_by_date(month, year) - projects = Project.conversions.confirmed.filtered_by_significant_date(month, year) - - AcademiesApiPreFetcherService.new.call!(projects) if @pre_fetch_academies_api - sort_by_conditions_met_and_name(projects) - end - - def transfer_projects_by_date(month, year) - projects = Project.transfers.confirmed.filtered_by_significant_date(month, year) - - AcademiesApiPreFetcherService.new.call!(projects) if @pre_fetch_academies_api - sort_by_conditions_met_and_name(projects) - end - - private def sort_by_conditions_met_and_name(projects) - projects.sort_by { |p| [p.all_conditions_met? ? 0 : 1, p.establishment.name] } - end end diff --git a/app/services/export/conversions/pre_conversion_grants_csv_export_service.rb b/app/services/export/conversions/pre_conversion_grants_csv_export_service.rb index d0bf22492..e636c5a51 100644 --- a/app/services/export/conversions/pre_conversion_grants_csv_export_service.rb +++ b/app/services/export/conversions/pre_conversion_grants_csv_export_service.rb @@ -14,6 +14,7 @@ class Export::Conversions::PreConversionGrantsCsvExportService < Export::CsvExpo conversion_date date_academy_opened academy_order_type + dao_revoked completed_grant_payment_certificate_received two_requires_improvement sponsored_grant_type diff --git a/app/services/export/conversions/rpa_sug_and_fa_letters_csv_export_service.rb b/app/services/export/conversions/rpa_sug_and_fa_letters_csv_export_service.rb index e71a53fa6..1768720ec 100644 --- a/app/services/export/conversions/rpa_sug_and_fa_letters_csv_export_service.rb +++ b/app/services/export/conversions/rpa_sug_and_fa_letters_csv_export_service.rb @@ -74,6 +74,7 @@ class Export::Conversions::RpaSugAndFaLettersCsvExportService < Export::CsvExpor date_academy_opened assigned_to_name assigned_to_email + assigned_to_team ] def initialize(projects) diff --git a/app/views/projects/show.html.erb b/app/views/projects/show.html.erb deleted file mode 100644 index df019032c..000000000 --- a/app/views/projects/show.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -<% content_for :pre_content_nav do %> - <% render partial: "shared/back_link", locals: {href: root_path} %> -<% end %> - -<%= render partial: "projects/shared/project_summary" %> - -<%= render partial: "shared/projects/actions" %> - -<%= render partial: "projects/shared/project_sub_navigation" %> - -<%= render "projects/show/complete" if policy(@project).update? %> diff --git a/app/views/projects/show/_dao_revocation.html.erb b/app/views/projects/show/_dao_revocation.html.erb new file mode 100644 index 000000000..7cd8bc007 --- /dev/null +++ b/app/views/projects/show/_dao_revocation.html.erb @@ -0,0 +1,7 @@ +
+
+

<%= t("dao_revocations.title") %>

+

<%= t("dao_revocations.body_html") %>

+ <%= link_to t("dao_revocations.button"), project_dao_revocation_start_path(@project), class: "govuk-button govuk-button--secondary" %> +
+
diff --git a/app/views/projects/show/_task_list.html.erb b/app/views/projects/show/_task_list.html.erb deleted file mode 100644 index d13169f8c..000000000 --- a/app/views/projects/show/_task_list.html.erb +++ /dev/null @@ -1,23 +0,0 @@ -
    - <% @project.sections.each do |section| %> -
  1. -

    - <%= section.title %> -

    - -
  2. - <% end %> -
diff --git a/app/views/shared/projects/_task_list.html.erb b/app/views/shared/projects/_task_list.html.erb index 302c09320..351fb1135 100644 --- a/app/views/shared/projects/_task_list.html.erb +++ b/app/views/shared/projects/_task_list.html.erb @@ -8,9 +8,13 @@ <%= render partial: "shared/side_navigation_item", locals: {name: t("#{section.locales_path}.title"), path: "##{section.identifier}"} %> <% end %> - <% unless @project.completed? %> + <% if @project.active? && policy(@project).update? %>
  • <%= link_to t("project.show.completing_a_project_link"), "#completing-a-project", class: "govuk-link govuk-link--no-visited-state" %>
  • <% end %> + + <% if @project.active? && @project.dao_revokable? && policy(@project).update? %> +
  • <%= link_to t("project.show.dao_revocation_link"), "#dao-revocation", class: "govuk-link govuk-link--no-visited-state" %>
  • + <% end %> @@ -43,9 +47,15 @@ <% end %> +
    <%= render "projects/show/complete" if @project.active? && policy(@project).update? %>
    + +
    + <%= render "projects/show/dao_revocation" if @project.active? && @project.dao_revokable? && policy(@project).update? %> +
    + diff --git a/config/locales/dao_revocations.en.yml b/config/locales/dao_revocations.en.yml index ebbbe3220..9c6ad43d7 100644 --- a/config/locales/dao_revocations.en.yml +++ b/config/locales/dao_revocations.en.yml @@ -1,5 +1,11 @@ en: dao_revocations: + project_not_revokable: Only conversion projects with a DAO (Directive Academy Order) can have the DAO revoked. + title: Revoke a Directive Academy Order + body_html: +

    You can record the decision to revoke a DAO (Directive Academy Order).

    +

    The decision must have been approved by a minister.

    + button: Record DAO revocation start: title: Record Directive Academy Order revocation body_html: diff --git a/config/locales/export/csv/project.en.yml b/config/locales/export/csv/project.en.yml index 33e3f4e1e..a5913ac15 100644 --- a/config/locales/export/csv/project.en.yml +++ b/config/locales/export/csv/project.en.yml @@ -12,6 +12,7 @@ en: risk_protection_arrangement_reason: Reason for commercial insurance advisory_board_date: Advisory board date academy_order_type: Academy order type + dao_revoked: Directive academy order revoked reception_to_six_years: Proposed capacity for pupils in reception to year 6 seven_to_eleven_years: Proposed capacity for pupils in years 7 to 11 twelve_or_above_years: Proposed capacity for students in year 12 or above diff --git a/config/locales/project.en.yml b/config/locales/project.en.yml index 64e7c6700..3512b3f63 100644 --- a/config/locales/project.en.yml +++ b/config/locales/project.en.yml @@ -15,6 +15,7 @@ en: edit_button: text: Edit completing_a_project_link: Completing a project + dao_revocation_link: Revoke a Directive Academy Order all: in_progress: title: All projects in progress diff --git a/spec/factories/dao_revocation_factory.rb b/spec/factories/dao_revocation_factory.rb new file mode 100644 index 000000000..e37277bee --- /dev/null +++ b/spec/factories/dao_revocation_factory.rb @@ -0,0 +1,10 @@ +FactoryBot.define do + factory :dao_revocation do + project { association :conversion_project } + decision_makers_name { "Minister Name" } + date_of_decision { Date.today - 1.week } + reason_school_rating_improved { false } + reason_safeguarding_addressed { false } + reason_school_closed { true } + end +end diff --git a/spec/features/all_projects/by_month/users_can_view_projects_by_month_spec.rb b/spec/features/all_projects/by_month/users_can_view_projects_by_month_spec.rb index 2c9ca47ce..dafaf330f 100644 --- a/spec/features/all_projects/by_month/users_can_view_projects_by_month_spec.rb +++ b/spec/features/all_projects/by_month/users_can_view_projects_by_month_spec.rb @@ -20,7 +20,7 @@ click_on "Apply" click_on "download a more detailed version of the data as a CSV file" - expect(page.response_headers["Content-Disposition"]).to include("2023-1-1-2023-12-1_schools_due_to_convert.csv") + expect(page.response_headers["Content-Disposition"]).to include("2023-01-01-2023-12-31_schools_due_to_convert.csv") end scenario "the user can download a CSV of transfer projects" do @@ -33,7 +33,7 @@ click_on "Apply" click_on "download a more detailed version of the data as a CSV file" - expect(page.response_headers["Content-Disposition"]).to include("2023-1-1-2023-12-1_academies_due_to_transfer.csv") + expect(page.response_headers["Content-Disposition"]).to include("2023-01-01-2023-12-31_academies_due_to_transfer.csv") end end diff --git a/spec/features/dao_revocation/user_can_record_the_revocation_of_a_dao_from_a_project_spec.rb b/spec/features/dao_revocation/user_can_record_the_revocation_of_a_dao_from_a_project_spec.rb index f0d6337b5..4ae0753aa 100644 --- a/spec/features/dao_revocation/user_can_record_the_revocation_of_a_dao_from_a_project_spec.rb +++ b/spec/features/dao_revocation/user_can_record_the_revocation_of_a_dao_from_a_project_spec.rb @@ -11,7 +11,13 @@ scenario "by providing all of the details correctly" do project = create(:conversion_project, directive_academy_order: true, assigned_to: user) - visit project_dao_revocation_start_path(project) + visit project_path(project) + + click_on "Revoke a Directive Academy Order" + + click_on "Record DAO revocation" + + expect(page).to have_content "Record Directive Academy Order revocation" click_on "Continue" @@ -45,7 +51,13 @@ scenario "they can change details before submitting" do project = create(:conversion_project, directive_academy_order: true, assigned_to: user) - visit project_dao_revocation_start_path(project) + visit project_path(project) + + click_on "Revoke a Directive Academy Order" + + click_on "Record DAO revocation" + + expect(page).to have_content "Record Directive Academy Order revocation" click_on "Continue" diff --git a/spec/forms/export/new_rpa_sug_and_fa_letters_form_spec.rb b/spec/forms/export/new_rpa_sug_and_fa_letters_form_spec.rb index a879ffdd2..8966d61e8 100644 --- a/spec/forms/export/new_rpa_sug_and_fa_letters_form_spec.rb +++ b/spec/forms/export/new_rpa_sug_and_fa_letters_form_spec.rb @@ -22,11 +22,15 @@ to_date = Date.new(2024, 4, 1) form = described_class.new(from_date: from_date, to_date: to_date) + allow(Project).to receive(:active).and_call_original + allow(Project).to receive(:completed).and_call_original allow(Project).to receive(:conversions).and_call_original allow(Project).to receive(:significant_date_in_range).and_call_original form.export + expect(Project).to have_received(:active) + expect(Project).to have_received(:completed) expect(Project).to have_received(:conversions) expect(Project).to have_received(:significant_date_in_range).with(from_date.to_s, to_date.to_s) end diff --git a/spec/presenters/export/csv/project_presenter_spec.rb b/spec/presenters/export/csv/project_presenter_spec.rb index abe721d1f..fb068cd7c 100644 --- a/spec/presenters/export/csv/project_presenter_spec.rb +++ b/spec/presenters/export/csv/project_presenter_spec.rb @@ -955,4 +955,37 @@ end end end + + describe "#dao_revoked" do + it "presents not applicable when dao revocation does not apply" do + project = build(:transfer_project) + + presenter = described_class.new(project) + + expect(presenter.dao_revoked).to eql "not applicable" + + project = build(:conversion_project, directive_academy_order: false) + + presenter = described_class.new(project) + + expect(presenter.dao_revoked).to eql "not applicable" + end + + it "presents 'no' when the dao has not be revoked" do + project = build(:conversion_project, directive_academy_order: true) + + presenter = described_class.new(project) + + expect(presenter.dao_revoked).to eql "no" + end + + it "presents the date of the decision to revoke when it has been" do + project = build(:conversion_project, directive_academy_order: true, state: :dao_revoked) + dao_revocation = create(:dao_revocation, project: project) + + presenter = described_class.new(project) + + expect(presenter.dao_revoked).to eql dao_revocation.date_of_decision.to_fs(:csv) + end + end end diff --git a/spec/requests/dao_revocations_controller_spec.rb b/spec/requests/dao_revocations_controller_spec.rb index e96f03dce..8f48bea82 100644 --- a/spec/requests/dao_revocations_controller_spec.rb +++ b/spec/requests/dao_revocations_controller_spec.rb @@ -9,6 +9,36 @@ mock_all_academies_api_responses end + describe "only revokable projects" do + it "redirects to the project view unless the project is dao revokable" do + project = create(:conversion_project, directive_academy_order: false, assigned_to: user) + + get project_dao_revocation_start_path(project) + + expect(response).to redirect_to project_path(project) + follow_redirect! + follow_redirect! + expect(response.body).to include "Only conversion projects with a DAO" + + project = create(:transfer_project, assigned_to: user) + + get project_dao_revocation_start_path(project) + + expect(response).to redirect_to project_path(project) + follow_redirect! + follow_redirect! + expect(response.body).to include "Only conversion projects with a DAO" + end + + it "renders when the project is DAO revokable" do + project = create(:conversion_project, directive_academy_order: true, assigned_to: user) + + get project_dao_revocation_start_path(project) + + expect(response).to render_template "start" + end + end + describe "#step" do it "renders the template for the step" do get project_dao_revocation_step_path(project, :reasons) diff --git a/spec/requests/tasks_controller_spec.rb b/spec/requests/tasks_controller_spec.rb index f5a9f2577..987c23db5 100644 --- a/spec/requests/tasks_controller_spec.rb +++ b/spec/requests/tasks_controller_spec.rb @@ -70,4 +70,136 @@ end end end + + describe "side navigation" do + before do + mock_all_academies_api_responses + end + + describe "link to completing the project" do + it "shows the link to complete a project" do + conversion_project = create(:conversion_project, assigned_to: user) + transfer_project = create(:transfer_project, assigned_to: user) + + get project_tasks_path(conversion_project) + + expect(response.body).to include "#completing-a-project" + + get project_tasks_path(transfer_project) + + expect(response.body).to include "#completing-a-project" + end + + it "does not show a link when the user is not authorised" do + conversion_project = create(:conversion_project, assigned_to: nil) + transfer_project = create(:transfer_project, assigned_to: nil) + + get project_tasks_path(conversion_project) + + expect(response.body).not_to include "#completing-a-project" + + get project_tasks_path(transfer_project) + + expect(response.body).not_to include "#completing-a-project" + end + + it "does not show a link when the project is complete" do + conversion_project = create(:conversion_project, assigned_to: user, state: :completed, completed_at: Date.today) + transfer_project = create(:transfer_project, assigned_to: user, state: :completed, completed_at: Date.today) + + get project_tasks_path(conversion_project) + + expect(response.body).not_to include "#completing-a-project" + + get project_tasks_path(transfer_project) + + expect(response.body).not_to include "#completing-a-project" + end + + it "does not show when the project is DAO revoked" do + conversion_project = create(:conversion_project, assigned_to: user, directive_academy_order: true, state: :dao_revoked) + create(:dao_revocation, project: conversion_project) + + get project_tasks_path(conversion_project) + + expect(response.body).not_to include "#completing-a-project" + end + end + + describe "link to DAO revocation" do + it "shows on conversions that have a DAO" do + conversion_project = create( + :conversion_project, + assigned_to: user, + directive_academy_order: true + ) + + get project_tasks_path(conversion_project) + + expect(response.body).to include "#dao-revocation" + end + + it "does not show if the user is not authorised" do + conversion_project = create( + :conversion_project, + assigned_to: nil, + directive_academy_order: true + ) + + get project_tasks_path(conversion_project) + + expect(response.body).not_to include "#dao-revocation" + end + + it "does not show on transfers" do + transfer_project = create( + :transfer_project, + assigned_to: user + ) + + get project_tasks_path(transfer_project) + + expect(response.body).not_to include "#dao-revocation" + end + + it "does not show on conversion without a DAO" do + conversion_project = create( + :conversion_project, + assigned_to: user, + directive_academy_order: false + ) + + get project_tasks_path(conversion_project) + + expect(response.body).not_to include "#dao-revocation" + end + + it "does not show on projects that have already had the DAO revoked" do + conversion_project = create( + :conversion_project, + assigned_to: user, + directive_academy_order: true, + state: :dao_revoked + ) + create(:dao_revocation, project: conversion_project) + + get project_tasks_path(conversion_project) + + expect(response.body).not_to include "#dao-revocation" + end + + it "does not show when the project is complete" do + conversion_project = create( + :conversion_project, + assigned_to: user, + state: :completed, + completed_at: Date.today, + directive_academy_order: true + ) + get project_tasks_path(conversion_project) + + expect(response.body).not_to include "#dao-revocation" + end + end + end end diff --git a/spec/services/by_month_project_fetcher_service_spec.rb b/spec/services/by_month_project_fetcher_service_spec.rb index e8c9bfcdf..f9e0cd7cc 100644 --- a/spec/services/by_month_project_fetcher_service_spec.rb +++ b/spec/services/by_month_project_fetcher_service_spec.rb @@ -7,6 +7,40 @@ mock_all_academies_api_responses end + it "only includes active projects that are assigned to a user" do + significant_date = Date.parse("2023-1-1") + user = create(:user) + dao_project = create( + :conversion_project, + significant_date: significant_date, + significant_date_provisional: false, + directive_academy_order: true, + state: :dao_revoked, + assigned_to: user + ) + create(:dao_revocation, project: dao_project) + + _completed_project = create( + :conversion_project, + completed_at: Date.today, + state: :completed, + significant_date: significant_date, + significant_date_provisional: false, + assigned_to: user + ) + + _unassigned_project = create( + :conversion_project, + significant_date: significant_date, + significant_date_provisional: false, + assigned_to: nil + ) + + result = described_class.new.conversion_projects_by_date_range("2023-1-1", "2023-1-1") + + expect(result).to be_empty + end + it "returns all conversion projects with a confirmed date in the desired range, and orders by significant date" do january = Date.parse("2023-1-1") february = Date.parse("2023-2-1") @@ -37,6 +71,31 @@ mock_all_academies_api_responses end + it "only includes active projects that are assigned to a user" do + significant_date = Date.parse("2023-1-1") + user = create(:user) + + _completed_project = create( + :transfer_project, + completed_at: Date.today, + state: :completed, + significant_date: significant_date, + significant_date_provisional: false, + assigned_to: user + ) + + _unassigned_project = create( + :transfer_project, + significant_date: significant_date, + significant_date_provisional: false, + assigned_to: nil + ) + + result = described_class.new.transfer_projects_by_date_range("2023-1-1", "2023-1-1") + + expect(result).to be_empty + end + it "returns all transfer projects with a confirmed date in the desired range, and orders by significant date" do january = Date.parse("2023-1-1") february = Date.parse("2023-2-1") @@ -60,38 +119,4 @@ end end end - - describe "#conversion_projects_by_date" do - context "with prefetching disabled for this test" do - it "returns conversion projects and orders by all conditions met & establishment name" do - project_one = double(Conversion::Project, all_conditions_met?: false, establishment: double("Establishment", name: "Y school")) - project_two = double(Conversion::Project, all_conditions_met?: false, establishment: double("Establishment", name: "B school")) - project_three = double(Conversion::Project, all_conditions_met?: false, establishment: double("Establishment", name: "A school")) - project_four = double(Conversion::Project, all_conditions_met?: true, establishment: double("Establishment", name: "Z school")) - - allow(Project).to receive(:filtered_by_significant_date).and_return([project_one, project_two, project_three, project_four]) - - projects = described_class.new(pre_fetch_academies_api: false).conversion_projects_by_date(1, 2025) - - expect(projects).to eq [project_four, project_three, project_two, project_one] - end - end - end - - describe "#transfer_projects_by_date" do - context "with prefetching disabled for this test" do - it "returns transfer projects and orders by all conditions met & establishment name" do - project_one = double(Transfer::Project, all_conditions_met?: false, establishment: double("Establishment", name: "Y school")) - project_two = double(Transfer::Project, all_conditions_met?: false, establishment: double("Establishment", name: "B school")) - project_three = double(Transfer::Project, all_conditions_met?: false, establishment: double("Establishment", name: "A school")) - project_four = double(Transfer::Project, all_conditions_met?: true, establishment: double("Establishment", name: "Z school")) - - allow(Project).to receive(:filtered_by_significant_date).and_return([project_one, project_two, project_three, project_four]) - - projects = described_class.new(pre_fetch_academies_api: false).transfer_projects_by_date(1, 2025) - - expect(projects).to eq [project_four, project_three, project_two, project_one] - end - end - end end diff --git a/terraform/.terraform-version b/terraform/.terraform-version index 8decb929b..f8e233b27 100644 --- a/terraform/.terraform-version +++ b/terraform/.terraform-version @@ -1 +1 @@ -1.8.5 +1.9.0