diff --git a/.github/actions/deploy-environment/action.yml b/.github/actions/deploy-environment/action.yml index b1d052fd88..31ab84369e 100644 --- a/.github/actions/deploy-environment/action.yml +++ b/.github/actions/deploy-environment/action.yml @@ -14,6 +14,16 @@ inputs: pull-request-number: description: The pull request number which triggered this deploy. required: false + prepare-database: + description: Whether to prepare the database by running migrations or seeding if needed + required: false + default: true + aks-namespace: + description: The namespace under which kubectl will run + required: true + aks-deployment: + description: The deployment which kubectl will target for running migrations + required: true runs: using: composite @@ -42,3 +52,19 @@ runs: run: | output=$(terraform -chdir=terraform/application output -raw url) echo "APP_URL=$output" >> $GITHUB_ENV + + - uses: azure/login@v2 + with: + creds: ${{ inputs.azure-credentials }} + + - name: Set kubectl + uses: DFE-Digital/github-actions/set-kubectl@master + + - name: Prepare database + if: ${{ inputs.prepare-database }} + shell: bash + run: | + make ci ${{ inputs.environment }} get-cluster-credentials + kubectl exec -n ${{ inputs.aks-namespace }} deployment/${{ inputs.aks-deployment }}-worker -- sh -c "DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bin/prepare-database" + env: + PR_NUMBER: ${{ inputs.pull-request-number }} diff --git a/.github/workflows/build_and_deploy.yml b/.github/workflows/build_and_deploy.yml index cdd0bbdb94..9ab72e5a82 100644 --- a/.github/workflows/build_and_deploy.yml +++ b/.github/workflows/build_and_deploy.yml @@ -50,22 +50,9 @@ jobs: docker-image: ${{ needs.build.outputs.docker-image-tag }} azure-credentials: ${{ secrets.AZURE_CREDENTIALS }} pull-request-number: ${{ github.event.pull_request.number }} - - - uses: azure/login@v2 - with: - creds: ${{ secrets.AZURE_CREDENTIALS }} - - - name: Set kubectl - uses: DFE-Digital/github-actions/set-kubectl@master - - - name: Seed review app - shell: bash - if: github.event.number != '' - run: | - make ci review-aks get-cluster-credentials - kubectl exec -n srtl-development deployment/claim-additional-payments-for-teaching-review-${{ github.event.pull_request.number }}-worker -- sh -c "DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bin/prepare-database" - env: - PR_NUMBER: ${{ github.event.pull_request.number }} + aks-namespace: srtl-development + aks-deployment: claim-additional-payments-for-teaching-review-${{ github.event.pull_request.number }} + prepare-database: ${{ github.event.pull_request.number != '' }} - name: Post comment to Pull Request ${{ github.event.number }} if: ${{ github.event_name == 'pull_request' }} @@ -83,17 +70,21 @@ jobs: | Relocation Payments | <${{ env.APP_URL }}/get-a-teacher-relocation-payment/landing-page> | | Admin | <${{ env.APP_URL }}/admin> | - deploy_test: - name: Deploy to test environment - concurrency: deploy_test + deploy: + name: Deploy to ${{ matrix.environment }} runs-on: ubuntu-latest + concurrency: deploy_${{ matrix.environment }} if: github.ref == 'refs/heads/master' && github.event_name == 'push' needs: [build] environment: - name: test-aks + name: ${{ matrix.environment }}-aks url: ${{ steps.deploy.outputs.environment_url }} outputs: environment_url: ${{ steps.deploy.outputs.environment_url }} + strategy: + max-parallel: 1 + matrix: + environment: [test, production] steps: - name: Checkout code @@ -106,15 +97,11 @@ jobs: - uses: ./.github/actions/deploy-environment id: deploy with: - environment: test-aks + environment: ${{ matrix.environment }}-aks docker-image: ${{ needs.build.outputs.docker-image-tag }} azure-credentials: ${{ secrets.AZURE_CREDENTIALS }} - - - name: Run migrations - shell: bash - run: | - make ci test-aks get-cluster-credentials - kubectl exec -n srtl-test deployment/claim-additional-payments-for-teaching-test-worker -- sh -c "DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bin/prepare-database" + aks-namespace: srtl-${{ matrix.environment }} + aks-deployment: claim-additional-payments-for-teaching-${{ matrix.environment }} - name: Install Ruby uses: ruby/setup-ruby@v1 @@ -126,7 +113,7 @@ jobs: run: bundle exec rspec spec/smoke -t smoke:true -b env: RAILS_ENV: test - SMOKE_TEST_APP_HOST: ${{ env.APP_URL }} + SMOKE_TEST_APP_HOST: ${{ vars.SMOKE_TEST_APP_HOST }} BASIC_AUTH_USERNAME: ${{ secrets.BASIC_AUTH_USERNAME }} BASIC_AUTH_PASSWORD: ${{ secrets.BASIC_AUTH_PASSWORD }} @@ -135,6 +122,8 @@ jobs: uses: rtCamp/action-slack-notify@master env: SLACK_COLOR: failure - SLACK_TITLE: Failure deploying release to test - SLACK_MESSAGE: Failure deploying release to test - Docker tag ${{ needs.build.outputs.docker-image-tag }} + SLACK_TITLE: Failure deploying release to ${{ matrix.environment }} + SLACK_MESSAGE: + Failure deploying release to ${{ matrix.environment }} - Docker tag ${{ needs.build.outputs.docker-image-tag + }} SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} diff --git a/.github/workflows/database_backup.yml b/.github/workflows/database_backup.yml new file mode 100644 index 0000000000..ac3ee53afd --- /dev/null +++ b/.github/workflows/database_backup.yml @@ -0,0 +1,24 @@ +name: Backup Database to Azure Storage +concurrency: build_and_deploy_main + +on: + workflow_dispatch: + schedule: # 03:00 UTC + - cron: "0 3 * * *" + +jobs: + backup: + name: Backup AKS Database (production) + runs-on: ubuntu-latest + environment: production-aks + + steps: + - name: Backup postgres + uses: DFE-Digital/github-actions/backup-postgres@master + with: + storage-account: s189p01captdbbkppdsa + resource-group: s189p01-capt-pd-rg + app-name: claim-additional-payments-for-teaching-production-web + cluster: production + azure-credentials: ${{ secrets.AZURE_CREDENTIALS }} + backup-file: capt_prod_$(date +"%F").sql diff --git a/.github/workflows/database_restore.yml b/.github/workflows/database_restore.yml new file mode 100644 index 0000000000..68a82df193 --- /dev/null +++ b/.github/workflows/database_restore.yml @@ -0,0 +1,44 @@ +name: Restore Database from Azure Storage +concurrency: build_and_deploy_main + +on: + workflow_dispatch: + inputs: + confirm: + description: Set to true to restore nightly backup to production + required: true + default: 'false' + type: choice + options: + - 'false' + - 'true' + backup-file: + description: Name of the backup file in Azure storage. e.g. capt_prod_2024-07-15.sql.gz. The default value is today's backup. + type: string + +jobs: + restore: + name: Restore AKS Database (production) + if: inputs.confirm == 'true' + runs-on: ubuntu-latest + environment: production-aks + + steps: + - name: Set backup file + run: | + if [ "${{ inputs.backup-file }}" != "" ]; then + BACKUP_FILE=${{ inputs.backup-file }} + else + BACKUP_FILE=capt_prod_$(date +"%F").sql.gz + fi + echo "BACKUP_FILE=$BACKUP_FILE" >> $GITHUB_ENV + + - name: Restore postgres + uses: DFE-Digital/github-actions/restore-postgres-backup@master + with: + storage-account: s189p01captdbbkppdsa + resource-group: s189p01-capt-pd-rg + app-name: claim-additional-payments-for-teaching-production-web + cluster: production + azure-credentials: ${{ secrets.AZURE_CREDENTIALS }} + backup-file: ${{ env.BACKUP_FILE }} diff --git a/Dockerfile b/Dockerfile index 1fddd9b44e..52e414396c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -53,22 +53,7 @@ WORKDIR ${APP_HOME} EXPOSE 3000 -CMD /filebeat/filebeat -c /filebeat/filebeat.yml & bundle exec rails server - -# Download and install filebeat for sending logs to logstash -ENV FILEBEAT_VERSION=7.6.2 -ENV FILEBEAT_DOWNLOAD_PATH=/tmp/filebeat.tar.gz -ENV FILEBEAT_CHECKSUM=482304509aed80db78ef63a0fed88e4453ebe7b11f6b4ab3168036a78f6a413e2f6a5c039f405e13984653b1a094c23f7637ac7daf3da75a032692d1c34a9b65 - -RUN curl https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-${FILEBEAT_VERSION}-linux-x86_64.tar.gz -o ${FILEBEAT_DOWNLOAD_PATH} && \ - [ "$(sha512sum ${FILEBEAT_DOWNLOAD_PATH})" = "${FILEBEAT_CHECKSUM} ${FILEBEAT_DOWNLOAD_PATH}" ] && \ - tar xzvf ${FILEBEAT_DOWNLOAD_PATH} && \ - rm ${FILEBEAT_DOWNLOAD_PATH} && \ - mv filebeat-${FILEBEAT_VERSION}-linux-x86_64 /filebeat && \ - rm -f /filebeat/filebeat.yml - -# Copy our local filebeat config to the installation -COPY filebeat.yml /filebeat/filebeat.yml +CMD bundle exec rails server # Copy dependencies (relying on dependencies using the same base image as this) COPY --from=dependencies ${DEPS_HOME}/Gemfile ${APP_HOME}/Gemfile @@ -96,7 +81,7 @@ RUN DFE_SIGN_IN_API_CLIENT_ID= \ SUPPRESS_DFE_ANALYTICS_INIT= \ bundle exec rake assets:precompile -RUN chown -hR appuser:appgroup ${APP_HOME} /filebeat +RUN chown -hR appuser:appgroup ${APP_HOME} USER appuser diff --git a/Gemfile.lock b/Gemfile.lock index a113c9b12d..160b02f83b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -292,6 +292,8 @@ GEM nokogiri (1.16.6) mini_portile2 (~> 2.8.2) racc (~> 1.4) + nokogiri (1.16.6-arm64-darwin) + racc (~> 1.4) nokogiri (1.16.6-x86_64-darwin) racc (~> 1.4) nokogiri (1.16.6-x86_64-linux) @@ -398,7 +400,7 @@ GEM request_store_rails (2.0.0) concurrent-ruby (~> 1.0) retriable (3.1.2) - rexml (3.3.1) + rexml (3.3.2) strscan rollbar (3.5.2) rotp (6.3.0) @@ -551,6 +553,7 @@ GEM zeitwerk (2.6.16) PLATFORMS + arm64-darwin-23 ruby x86_64-darwin-21 x86_64-linux diff --git a/README.md b/README.md index dead1684f9..a28f722801 100644 --- a/README.md +++ b/README.md @@ -295,17 +295,6 @@ STRONGLY discouraged.** The console will be ran inside a container instance and won't be on one of the web servers, however it will have access to the database. -### Through the Azure UI - -- Navigate to the - [container instance](https://portal.azure.com/#blade/HubsExtension/BrowseResourceBlade/resourceType/Microsoft.ContainerInstance%2FcontainerGroups) - resource (eg. `s118d01-app-worker-aci`) -- Then go to 'Containers' under 'Settings' -- With the container selected go to the 'Connect' tab -- Choose the start up command (`/bin/bash` is recommended) and connect -- From there, you can run a Rails console with `bin/rails console`. Pass the - `--sandbox` flag if you don’t need to modify data. - ### Through the Azure CLI We have a helpful script you can run that will connect you to the right resource diff --git a/app/controllers/admin/eligible_fe_providers_controller.rb b/app/controllers/admin/eligible_fe_providers_controller.rb new file mode 100644 index 0000000000..9bc57edfc7 --- /dev/null +++ b/app/controllers/admin/eligible_fe_providers_controller.rb @@ -0,0 +1,45 @@ +module Admin + class EligibleFeProvidersController < BaseAdminController + before_action :ensure_service_operator + + helper_method :journey_configuration + + def create + @download_form = EligibleFeProvidersForm.new + @upload_form = EligibleFeProvidersForm.new(upload_params) + + if @upload_form.invalid? + render "admin/journey_configurations/edit" + else + @upload_form.importer.run + flash[:notice] = @upload_form.importer.results_message + + redirect_to edit_admin_journey_configuration_path(Journeys::FurtherEducationPayments::ROUTING_NAME, eligible_fe_providers_upload: {academic_year: @upload_form.academic_year}) + end + end + + def show + @download_form = EligibleFeProvidersForm.new(download_params) + + send_data EligibleFeProvider.csv_for_academic_year(@download_form.academic_year), + type: "text/csv", + filename: "eligible_further_education_providers_#{@download_form.academic_year}.csv" + end + + private + + def journey_configuration + @journey_configuration ||= Journeys::Configuration.find_by( + routing_name: Journeys::FurtherEducationPayments::ROUTING_NAME + ) + end + + def upload_params + params.require(:eligible_fe_providers_upload).permit(:academic_year, :file) + end + + def download_params + params.require(:eligible_fe_providers_download).permit(:academic_year) + end + end +end diff --git a/app/controllers/admin/journey_configurations_controller.rb b/app/controllers/admin/journey_configurations_controller.rb index 5ae90980ae..86ecc4a2c2 100644 --- a/app/controllers/admin/journey_configurations_controller.rb +++ b/app/controllers/admin/journey_configurations_controller.rb @@ -10,6 +10,9 @@ def index def edit @csv_upload = Policies::LevellingUpPremiumPayments::AwardCsvImporter.new if journey_configuration.additional_payments? + + @upload_form = EligibleFeProvidersForm.new(upload_params) + @download_form = EligibleFeProvidersForm.new end def update @@ -19,6 +22,10 @@ def update private + def upload_params + params.fetch(:eligible_fe_providers_upload, {}).permit(:academic_year) + end + def journey_configuration return unless params[:id].present? diff --git a/app/forms/admin/eligible_fe_providers_form.rb b/app/forms/admin/eligible_fe_providers_form.rb new file mode 100644 index 0000000000..eced541748 --- /dev/null +++ b/app/forms/admin/eligible_fe_providers_form.rb @@ -0,0 +1,35 @@ +class Admin::EligibleFeProvidersForm + include ActiveModel::Model + include ActiveModel::Attributes + + attribute :academic_year, AcademicYear::Type.new + attribute :file + + validates :file, + presence: {message: "Choose a CSV file of eligible FE providers to upload"} + + validate :validate_importer_errors + + def select_options + (0..2).map do |relative_year| + academic_year = AcademicYear.current + relative_year + OpenStruct.new(id: academic_year.to_s, name: academic_year) + end + end + + def importer + @importer ||= EligibleFeProvidersImporter.new( + file, + academic_year + ) + end + + private + + # importer is not activemodel::errors compliant + def validate_importer_errors + importer.errors.each do |error| + errors.add(:file, error) + end + end +end diff --git a/app/forms/claim_submission_base_form.rb b/app/forms/claim_submission_base_form.rb index b972d68d47..b3e69378ac 100644 --- a/app/forms/claim_submission_base_form.rb +++ b/app/forms/claim_submission_base_form.rb @@ -1,10 +1,11 @@ class ClaimSubmissionBaseForm include ActiveModel::Model + include FormHelpers attr_reader :journey_session, :claim validate :not_already_submitted - validate :email_address_is_preesent + validate :email_address_is_present validate :email_address_verified validate :mobile_number_verified validate :claim_is_eligible @@ -79,13 +80,13 @@ def generate_reference def not_already_submitted if journey_session.submitted? - errors.add(:base, i18n_error_message(:already_submitted)) + errors.add(:base, i18n_errors_path(:already_submitted)) end end - def email_address_is_preesent + def email_address_is_present if answers.email_address.blank? - errors.add(:email_address, i18n_error_message(:email_address)) + errors.add(:email_address, i18n_errors_path(:email_address)) end end @@ -93,7 +94,7 @@ def email_address_verified return unless answers.email_address.present? unless answers.email_verified - errors.add(:email_verified, i18n_error_message(:email_verified)) + errors.add(:email_verified, i18n_errors_path(:email_verified)) end end @@ -101,7 +102,7 @@ def mobile_number_verified unless mobile_number_verified? errors.add( :base, - i18n_error_message(:mobile_number_verified) + i18n_errors_path(:mobile_number_verified) ) end end @@ -117,7 +118,7 @@ def mobile_number_verified? def claim_is_eligible if main_eligibility.policy::PolicyEligibilityChecker.new(answers: answers).ineligible? - errors.add(:base, i18n_error_message(:ineligible)) + errors.add(:base, i18n_errors_path(:ineligible)) end end @@ -126,10 +127,6 @@ def main_claim_is_submittable claim.errors.full_messages.each { |message| errors.add(:base, message) } end - def i18n_error_message(attr) - I18n.t("#{journey::I18N_NAMESPACE}.forms.claim_submission_form.errors.#{attr}") - end - def journey self.class.module_parent end diff --git a/app/forms/form.rb b/app/forms/form.rb index 48c282a81e..3fddc0005c 100644 --- a/app/forms/form.rb +++ b/app/forms/form.rb @@ -3,6 +3,7 @@ class Form include ActiveModel::Attributes include ActiveModel::Serialization include ActiveModel::Validations::Callbacks + include FormHelpers attr_accessor :journey attr_accessor :journey_session @@ -29,19 +30,6 @@ def view_path journey::VIEW_PATH end - def i18n_namespace - journey::I18N_NAMESPACE - end - - def i18n_errors_path(msg, args = {}) - base_key = :"forms.#{i18n_form_namespace}.errors.#{msg}" - I18n.t("#{i18n_namespace}.#{base_key}", default: base_key, **args) - end - - def t(key, args = {}) - I18n.t(key, scope: "#{i18n_namespace}.forms.#{i18n_form_namespace}", **args) - end - def permitted_params @permitted_params ||= params.fetch(model_name.param_key, {}).permit(*permitted_attributes) end @@ -65,10 +53,6 @@ def permitted_attributes end end - def i18n_form_namespace - self.class.name.demodulize.gsub("Form", "").underscore - end - def attributes_with_current_value attributes.each_with_object({}) do |(attribute, _), hash| hash[attribute] = permitted_params[attribute] diff --git a/app/forms/form_helpers.rb b/app/forms/form_helpers.rb new file mode 100644 index 0000000000..6447ebb714 --- /dev/null +++ b/app/forms/form_helpers.rb @@ -0,0 +1,23 @@ +module FormHelpers + def i18n_namespace + journey::I18N_NAMESPACE + end + + def i18n_errors_path(key, args = {}) + base_key = :"forms.#{i18n_form_namespace}.errors.#{key}" + I18n.t("#{i18n_namespace}.#{base_key}", default: base_key, **args) + end + + def t(key, args = {}) + i18n_form_namespace_dup = args.delete(:i18n_form_namespace) || i18n_form_namespace + + base_key = :"forms.#{i18n_form_namespace_dup}.#{key}" + I18n.t("#{i18n_namespace}.#{base_key}", default: base_key, **args) + end + + private + + def i18n_form_namespace + self.class.name.demodulize.gsub("Form", "").underscore + end +end diff --git a/app/forms/journeys/further_education_payments/building_construction_courses_form.rb b/app/forms/journeys/further_education_payments/building_construction_courses_form.rb new file mode 100644 index 0000000000..4c812575cd --- /dev/null +++ b/app/forms/journeys/further_education_payments/building_construction_courses_form.rb @@ -0,0 +1,61 @@ +module Journeys + module FurtherEducationPayments + class BuildingConstructionCoursesForm < Form + include CoursesHelper + + attribute :building_construction_courses, default: [] + + before_validation :clean_courses + + validates :building_construction_courses, + presence: {message: i18n_error_message(:inclusion)}, + inclusion: {in: ->(form) { form.checkbox_options.map(&:id) }, message: i18n_error_message(:inclusion)} + + def course_field + :building_construction_courses + end + + def checkbox_options + [ + OpenStruct.new( + id: "esfa_buildingconstruction", + name: course_option_description("esfa_buildingconstruction") + ), + OpenStruct.new( + id: "tlevel_building", + name: course_option_description("tlevel_building") + ), + OpenStruct.new( + id: "tlevel_onsiteconstruction", + name: course_option_description("tlevel_onsiteconstruction") + ), + OpenStruct.new( + id: "tlevel_design_surveying", + name: course_option_description("tlevel_design_surveying") + ), + OpenStruct.new( + id: "level2_3_apprenticeship", + name: course_option_description("level2_3_apprenticeship") + ), + OpenStruct.new( + id: "none", + name: course_option_description("none") + ) + ] + end + + def save + return false if invalid? + + journey_session.answers.assign_attributes(building_construction_courses:) + journey_session.save! + end + + private + + def clean_courses + building_construction_courses.reject!(&:blank?) + end + end + end +end diff --git a/app/forms/journeys/further_education_payments/check_your_answers_form.rb b/app/forms/journeys/further_education_payments/check_your_answers_form.rb deleted file mode 100644 index ead9c4a800..0000000000 --- a/app/forms/journeys/further_education_payments/check_your_answers_form.rb +++ /dev/null @@ -1,9 +0,0 @@ -module Journeys - module FurtherEducationPayments - class CheckYourAnswersForm < Form - def save - true - end - end - end -end diff --git a/app/forms/journeys/further_education_payments/chemistry_courses_form.rb b/app/forms/journeys/further_education_payments/chemistry_courses_form.rb new file mode 100644 index 0000000000..006e86fdfb --- /dev/null +++ b/app/forms/journeys/further_education_payments/chemistry_courses_form.rb @@ -0,0 +1,53 @@ +module Journeys + module FurtherEducationPayments + class ChemistryCoursesForm < Form + include CoursesHelper + + attribute :chemistry_courses, default: [] + + before_validation :clean_courses + + validates :chemistry_courses, + presence: {message: i18n_error_message(:inclusion)}, + inclusion: {in: ->(form) { form.checkbox_options.map(&:id) }, message: i18n_error_message(:inclusion)} + + def course_field + :chemistry_courses + end + + def checkbox_options + [ + OpenStruct.new( + id: "alevel_chemistry", + name: course_option_description("alevel_chemistry") + ), + OpenStruct.new( + id: "gcse_chemistry", + name: course_option_description("gcse_chemistry") + ), + OpenStruct.new( + id: "ib_certificate_chemistry", + name: course_option_description("ib_certificate_chemistry") + ), + OpenStruct.new( + id: "none", + name: course_option_description("none") + ) + ] + end + + def save + return false if invalid? + + journey_session.answers.assign_attributes(chemistry_courses:) + journey_session.save! + end + + private + + def clean_courses + chemistry_courses.reject!(&:blank?) + end + end + end +end diff --git a/app/forms/journeys/further_education_payments/computing_courses_form.rb b/app/forms/journeys/further_education_payments/computing_courses_form.rb new file mode 100644 index 0000000000..fc2f5c2720 --- /dev/null +++ b/app/forms/journeys/further_education_payments/computing_courses_form.rb @@ -0,0 +1,73 @@ +module Journeys + module FurtherEducationPayments + class ComputingCoursesForm < Form + include CoursesHelper + + attribute :computing_courses, default: [] + + before_validation :clean_courses + + validates :computing_courses, + presence: {message: i18n_error_message(:inclusion)}, + inclusion: {in: ->(form) { form.checkbox_options.map(&:id) }, message: i18n_error_message(:inclusion)} + + def course_field + :computing_courses + end + + def checkbox_options + [ + OpenStruct.new( + id: "esfa_digitalpractitioners", + name: course_option_description("esfa_digitalpractitioners") + ), + OpenStruct.new( + id: "esfa_digitalusers", + name: course_option_description("esfa_digitalusers") + ), + OpenStruct.new( + id: "digitalskills_quals", + name: course_option_description("digitalskills_quals") + ), + OpenStruct.new( + id: "tlevel_digitalsupport", + name: course_option_description("tlevel_digitalsupport") + ), + OpenStruct.new( + id: "tlevel_digitalbusiness", + name: course_option_description("tlevel_digitalbusiness") + ), + OpenStruct.new( + id: "tlevel_digitalproduction", + name: course_option_description("tlevel_digitalproduction") + ), + OpenStruct.new( + id: "ib_certificate_compsci", + name: course_option_description("ib_certificate_compsci") + ), + OpenStruct.new( + id: "level2_3_apprenticeship", + name: course_option_description("level2_3_apprenticeship") + ), + OpenStruct.new( + id: "none", + name: course_option_description("none") + ) + ] + end + + def save + return false if invalid? + + journey_session.answers.assign_attributes(computing_courses:) + journey_session.save! + end + + private + + def clean_courses + computing_courses.reject!(&:blank?) + end + end + end +end diff --git a/app/forms/journeys/further_education_payments/early_years_courses_form.rb b/app/forms/journeys/further_education_payments/early_years_courses_form.rb new file mode 100644 index 0000000000..80f5242f14 --- /dev/null +++ b/app/forms/journeys/further_education_payments/early_years_courses_form.rb @@ -0,0 +1,57 @@ +module Journeys + module FurtherEducationPayments + class EarlyYearsCoursesForm < Form + include CoursesHelper + + attribute :early_years_courses, default: [] + + before_validation :clean_courses + + validates :early_years_courses, + presence: {message: i18n_error_message(:inclusion)}, + inclusion: {in: ->(form) { form.checkbox_options.map(&:id) }, message: i18n_error_message(:inclusion)} + + def course_field + :early_years_courses + end + + def checkbox_options + [ + OpenStruct.new( + id: "eylevel2", + name: course_option_description("eylevel2") + ), + OpenStruct.new( + id: "eylevel3", + name: course_option_description("eylevel3") + ), + OpenStruct.new( + id: "eytlevel", + name: course_option_description("eytlevel") + ), + OpenStruct.new( + id: "coursetoeyq", + name: course_option_description("coursetoeyq") + ), + OpenStruct.new( + id: "none", + name: course_option_description("none") + ) + ] + end + + def save + return false if invalid? + + journey_session.answers.assign_attributes(early_years_courses:) + journey_session.save! + end + + private + + def clean_courses + early_years_courses.reject!(&:blank?) + end + end + end +end diff --git a/app/forms/journeys/further_education_payments/engineering_manufacturing_courses_form.rb b/app/forms/journeys/further_education_payments/engineering_manufacturing_courses_form.rb new file mode 100644 index 0000000000..d0de0e3376 --- /dev/null +++ b/app/forms/journeys/further_education_payments/engineering_manufacturing_courses_form.rb @@ -0,0 +1,69 @@ +module Journeys + module FurtherEducationPayments + class EngineeringManufacturingCoursesForm < Form + include CoursesHelper + + attribute :engineering_manufacturing_courses, default: [] + + before_validation :clean_courses + + validates :engineering_manufacturing_courses, + presence: {message: i18n_error_message(:inclusion)}, + inclusion: {in: ->(form) { form.checkbox_options.map(&:id) }, message: i18n_error_message(:inclusion)} + + def course_field + :engineering_manufacturing_courses + end + + def checkbox_options + [ + OpenStruct.new( + id: "esfa_engineering", + name: course_option_description("esfa_engineering") + ), + OpenStruct.new( + id: "esfa_manufacturing", + name: course_option_description("esfa_manufacturing") + ), + OpenStruct.new( + id: "esfa_transportation", + name: course_option_description("esfa_transportation") + ), + OpenStruct.new( + id: "tlevel_design", + name: course_option_description("tlevel_design") + ), + OpenStruct.new( + id: "tlevel_maintenance", + name: course_option_description("tlevel_maintenance") + ), + OpenStruct.new( + id: "tlevel_engineering", + name: course_option_description("tlevel_engineering") + ), + OpenStruct.new( + id: "level2_3_apprenticeship", + name: course_option_description("level2_3_apprenticeship") + ), + OpenStruct.new( + id: "none", + name: course_option_description("none") + ) + ] + end + + def save + return false if invalid? + + journey_session.answers.assign_attributes(engineering_manufacturing_courses:) + journey_session.save! + end + + private + + def clean_courses + engineering_manufacturing_courses.reject!(&:blank?) + end + end + end +end diff --git a/app/forms/journeys/further_education_payments/hours_teaching_eligible_subjects_form.rb b/app/forms/journeys/further_education_payments/hours_teaching_eligible_subjects_form.rb new file mode 100644 index 0000000000..727b80a268 --- /dev/null +++ b/app/forms/journeys/further_education_payments/hours_teaching_eligible_subjects_form.rb @@ -0,0 +1,45 @@ +module Journeys + module FurtherEducationPayments + class HoursTeachingEligibleSubjectsForm < Form + include CoursesHelper + + attribute :hours_teaching_eligible_subjects, :boolean + + validates :hours_teaching_eligible_subjects, + inclusion: { + in: [true, false], + message: i18n_error_message(:inclusion) + } + + def radio_options + [ + OpenStruct.new(id: true, name: "Yes"), + OpenStruct.new(id: false, name: "No") + ] + end + + def courses + ALL_COURSE_FIELDS.map { |course_field| + course_descriptions(course_field) + }.flatten + end + + def save + return false unless valid? + + journey_session.answers.assign_attributes(hours_teaching_eligible_subjects:) + journey_session.save! + end + + private + + def course_descriptions(course_field) + journey_session.answers.public_send(course_field).reject { |course| + course == "none" + }.map { |course| + course_option_description(course, i18n_form_namespace: course_field).html_safe + } + end + end + end +end diff --git a/app/forms/journeys/further_education_payments/maths_courses_form.rb b/app/forms/journeys/further_education_payments/maths_courses_form.rb new file mode 100644 index 0000000000..cc29e7cadc --- /dev/null +++ b/app/forms/journeys/further_education_payments/maths_courses_form.rb @@ -0,0 +1,49 @@ +module Journeys + module FurtherEducationPayments + class MathsCoursesForm < Form + include CoursesHelper + + attribute :maths_courses, default: [] + + before_validation :clean_courses + + validates :maths_courses, + presence: {message: i18n_error_message(:inclusion)}, + inclusion: {in: ->(form) { form.checkbox_options.map(&:id) }, message: i18n_error_message(:inclusion)} + + def course_field + :maths_courses + end + + def checkbox_options + [ + OpenStruct.new( + id: "esfa", + name: course_option_description("esfa") + ), + OpenStruct.new( + id: "gcse_maths", + name: course_option_description("gcse_maths") + ), + OpenStruct.new( + id: "none", + name: course_option_description("none") + ) + ] + end + + def save + return false if invalid? + + journey_session.answers.assign_attributes(maths_courses:) + journey_session.save! + end + + private + + def clean_courses + maths_courses.reject!(&:blank?) + end + end + end +end diff --git a/app/forms/journeys/further_education_payments/physics_courses_form.rb b/app/forms/journeys/further_education_payments/physics_courses_form.rb new file mode 100644 index 0000000000..6fe74ba9ed --- /dev/null +++ b/app/forms/journeys/further_education_payments/physics_courses_form.rb @@ -0,0 +1,53 @@ +module Journeys + module FurtherEducationPayments + class PhysicsCoursesForm < Form + include CoursesHelper + + attribute :physics_courses, default: [] + + before_validation :clean_courses + + validates :physics_courses, + presence: {message: i18n_error_message(:inclusion)}, + inclusion: {in: ->(form) { form.checkbox_options.map(&:id) }, message: i18n_error_message(:inclusion)} + + def course_field + :physics_courses + end + + def checkbox_options + [ + OpenStruct.new( + id: "alevel_physics", + name: course_option_description("alevel_physics") + ), + OpenStruct.new( + id: "gcse_physics", + name: course_option_description("gcse_physics") + ), + OpenStruct.new( + id: "ib_certificate_physics", + name: course_option_description("ib_certificate_physics") + ), + OpenStruct.new( + id: "none", + name: course_option_description("none") + ) + ] + end + + def save + return false if invalid? + + journey_session.answers.assign_attributes(physics_courses:) + journey_session.save! + end + + private + + def clean_courses + physics_courses.reject!(&:blank?) + end + end + end +end diff --git a/app/forms/journeys/further_education_payments/subjects_taught_form.rb b/app/forms/journeys/further_education_payments/subjects_taught_form.rb index a3998d4399..59c46205f1 100644 --- a/app/forms/journeys/further_education_payments/subjects_taught_form.rb +++ b/app/forms/journeys/further_education_payments/subjects_taught_form.rb @@ -2,6 +2,7 @@ module Journeys module FurtherEducationPayments class SubjectsTaughtForm < Form include ActiveModel::Validations::Callbacks + include CoursesHelper attribute :subjects_taught, default: [] @@ -12,20 +13,13 @@ class SubjectsTaughtForm < Form inclusion: {in: ->(form) { form.checkbox_options.map(&:id) }, message: i18n_error_message(:inclusion)} def checkbox_options - [ - OpenStruct.new(id: "building_and_construction", name: t("options.building_and_construction")), - OpenStruct.new(id: "chemistry", name: t("options.chemistry")), - OpenStruct.new(id: "computing", name: t("options.computing")), - OpenStruct.new(id: "early_years", name: t("options.early_years")), - OpenStruct.new(id: "engineering_and_manufacturing", name: t("options.engineering_and_manufacturing")), - OpenStruct.new(id: "mathematics", name: t("options.mathematics")), - OpenStruct.new(id: "physics", name: t("options.physics")), - OpenStruct.new(id: "none", name: t("options.none")) - ] + (ALL_SUBJECTS + ["none"]).map { |subject| OpenStruct.new(id: subject, name: t("options.#{subject}")) } end def save - return false unless valid? + return false if invalid? + + reset_dependent_answers journey_session.answers.assign_attributes(subjects_taught:) journey_session.save! @@ -36,6 +30,16 @@ def save def clean_subjects_taught subjects_taught.reject!(&:blank?) end + + def reset_dependent_answers + unchecked_subjects.each do |subject| + journey_session.answers.assign_attributes("#{subject}_courses" => []) + end + end + + def unchecked_subjects + journey_session.answers.subjects_taught - subjects_taught - ["none"] + end end end end diff --git a/app/forms/journeys/further_education_payments/teacher_reference_number_form.rb b/app/forms/journeys/further_education_payments/teacher_reference_number_form.rb new file mode 100644 index 0000000000..4d189d920b --- /dev/null +++ b/app/forms/journeys/further_education_payments/teacher_reference_number_form.rb @@ -0,0 +1,29 @@ +module Journeys + module FurtherEducationPayments + class TeacherReferenceNumberForm < Form + include TeacherReferenceNumberValidation + + attribute :teacher_reference_number + + before_validation :normalise_teacher_reference_number + + # NOTE: teacher_reference_number is optional, however validate if supplied + + validates :teacher_reference_number, + length: { + is: TRN_LENGTH, + message: ->(form, _) { form.i18n_errors_path("length") } + }, if: -> { teacher_reference_number.present? } + + def save + return false unless valid? + + journey_session.answers.assign_attributes( + teacher_reference_number: teacher_reference_number + ) + + journey_session.save! + end + end + end +end diff --git a/app/forms/journeys/further_education_payments/teaching_hours_per_week_next_term_form.rb b/app/forms/journeys/further_education_payments/teaching_hours_per_week_next_term_form.rb new file mode 100644 index 0000000000..fe8f724dfd --- /dev/null +++ b/app/forms/journeys/further_education_payments/teaching_hours_per_week_next_term_form.rb @@ -0,0 +1,36 @@ +module Journeys + module FurtherEducationPayments + class TeachingHoursPerWeekNextTermForm < Form + attribute :teaching_hours_per_week_next_term, :string + + validates :teaching_hours_per_week_next_term, + inclusion: {in: ->(form) { form.radio_options.map(&:id) }, message: i18n_error_message(:inclusion)} + + def radio_options + @radio_options ||= [ + OpenStruct.new( + id: "at_least_2_5", + name: t("options.at_least_2_5", school_name: school.name) + ), + OpenStruct.new( + id: "less_than_2_5", + name: t("options.less_than_2_5", school_name: school.name) + ) + ] + end + + def save + return false unless valid? + + journey_session.answers.assign_attributes(teaching_hours_per_week_next_term:) + journey_session.save! + end + + private + + def school + journey_session.answers.school + end + end + end +end diff --git a/app/forms/journeys/further_education_payments/teaching_responsibilities_form.rb b/app/forms/journeys/further_education_payments/teaching_responsibilities_form.rb index 7d9f872f80..430c3766da 100644 --- a/app/forms/journeys/further_education_payments/teaching_responsibilities_form.rb +++ b/app/forms/journeys/further_education_payments/teaching_responsibilities_form.rb @@ -17,7 +17,7 @@ def radio_options end def save - return false unless valid? + return false if invalid? journey_session.answers.assign_attributes(teaching_responsibilities:) journey_session.save! diff --git a/app/forms/journeys/get_a_teacher_relocation_payment/claim_submission_form.rb b/app/forms/journeys/get_a_teacher_relocation_payment/claim_submission_form.rb index 9e3b86743b..a9fad9c3db 100644 --- a/app/forms/journeys/get_a_teacher_relocation_payment/claim_submission_form.rb +++ b/app/forms/journeys/get_a_teacher_relocation_payment/claim_submission_form.rb @@ -8,9 +8,7 @@ def main_eligibility end def calculate_award_amount(eligibility) - # NOOP - # This is just for compatibility with the AdditionalPaymentsForTeaching - # claim submission form. + eligibility.award_amount = Policies::InternationalRelocationPayments.award_amount end def generate_policy_options_provided diff --git a/app/forms/mobile_number_form.rb b/app/forms/mobile_number_form.rb index fefdfa9320..13197e0e8c 100644 --- a/app/forms/mobile_number_form.rb +++ b/app/forms/mobile_number_form.rb @@ -33,6 +33,11 @@ def save private def send_sms_message + if Rails.env.development? + Rails.logger.info("SMS CODE: #{OneTimePassword::Generator.new.code}") + return true + end + NotifySmsMessage.new( phone_number: mobile_number, template_id: NotifySmsMessage::OTP_PROMPT_TEMPLATE_ID, diff --git a/app/forms/provide_mobile_number_form.rb b/app/forms/provide_mobile_number_form.rb index f71e21b48c..6159726018 100644 --- a/app/forms/provide_mobile_number_form.rb +++ b/app/forms/provide_mobile_number_form.rb @@ -6,8 +6,7 @@ class ProvideMobileNumberForm < Form inclusion: { in: [true, false], message: "Select yes if you would like to provide your mobile number" - }, - if: -> { answers.class.module_parent == Journeys::AdditionalPaymentsForTeaching } + } def save return false unless valid? diff --git a/app/mailers/claim_mailer.rb b/app/mailers/claim_mailer.rb index 752a64fb95..01360a9503 100644 --- a/app/mailers/claim_mailer.rb +++ b/app/mailers/claim_mailer.rb @@ -101,7 +101,8 @@ def unknown_policy_check(claim) Policies::StudentLoans, Policies::EarlyCareerPayments, Policies::LevellingUpPremiumPayments, - Policies::InternationalRelocationPayments + Policies::InternationalRelocationPayments, + Policies::FurtherEducationPayments ].include?(claim.policy) raise ArgumentError, "Unknown claim policy: #{claim.policy}" end diff --git a/app/models/claim_checking_tasks.rb b/app/models/claim_checking_tasks.rb index 29aca7c284..236d45b35c 100644 --- a/app/models/claim_checking_tasks.rb +++ b/app/models/claim_checking_tasks.rb @@ -12,8 +12,6 @@ def initialize(claim) delegate :policy, to: :claim def applicable_task_names - return %w[identity_confirmation visa arrival_date employment employment_contract employment_start subject] if policy.international_relocation_payments? - @applicable_task_names ||= Task::NAMES.dup.tap do |task_names| task_names.delete("induction_confirmation") unless claim.policy == Policies::EarlyCareerPayments task_names.delete("student_loan_amount") unless claim.policy == Policies::StudentLoans @@ -21,11 +19,17 @@ def applicable_task_names task_names.delete("payroll_details") unless claim.must_manually_validate_bank_details? task_names.delete("matching_details") unless matching_claims.exists? task_names.delete("payroll_gender") unless claim.payroll_gender_missing? || task_names_for_claim.include?("payroll_gender") - task_names.delete("visa") - task_names.delete("arrival_date") - task_names.delete("employment_contract") - task_names.delete("employment_start") - task_names.delete("subject") + if claim.policy.international_relocation_payments? + task_names.delete("qualifications") + task_names.delete("census_subjects_taught") + end + unless claim.policy.international_relocation_payments? + task_names.delete("visa") + task_names.delete("arrival_date") + task_names.delete("employment_contract") + task_names.delete("employment_start") + task_names.delete("subject") + end end end diff --git a/app/models/eligible_fe_provider.rb b/app/models/eligible_fe_provider.rb new file mode 100644 index 0000000000..de99c83331 --- /dev/null +++ b/app/models/eligible_fe_provider.rb @@ -0,0 +1,15 @@ +class EligibleFeProvider < ApplicationRecord + attribute :academic_year, AcademicYear::Type.new + + def self.csv_for_academic_year(academic_year) + attribute_names = [:ukprn, :max_award_amount, :lower_award_amount] + + CSV.generate(headers: true) do |csv| + csv << attribute_names + + where(academic_year:).each do |row| + csv << attribute_names.map { |attr| row.send(attr) } + end + end + end +end diff --git a/app/models/eligible_fe_providers_importer.rb b/app/models/eligible_fe_providers_importer.rb new file mode 100644 index 0000000000..c8dcf4fe73 --- /dev/null +++ b/app/models/eligible_fe_providers_importer.rb @@ -0,0 +1,38 @@ +class EligibleFeProvidersImporter < CsvImporter::Base + import_options( + target_data_model: EligibleFeProvider, + transform_rows_with: :row_to_hash, + mandatory_headers: %w[ + ukprn + max_award_amount + lower_award_amount + ] + ) + + attr_reader :academic_year + + def initialize(file, academic_year) + super(file) + + @academic_year = academic_year + end + + def results_message + "Replaced #{deleted_row_count} existing providers with #{rows.count} new providers" + end + + private + + def delete_all_scope + target_data_model.where(academic_year:) + end + + def row_to_hash(row) + { + ukprn: row.fetch("ukprn"), + max_award_amount: row.fetch("max_award_amount"), + lower_award_amount: row.fetch("lower_award_amount"), + academic_year: + } + end +end diff --git a/app/models/journeys/base_answers_presenter.rb b/app/models/journeys/base_answers_presenter.rb index a38cd304b6..44cf55b92e 100644 --- a/app/models/journeys/base_answers_presenter.rb +++ b/app/models/journeys/base_answers_presenter.rb @@ -13,7 +13,7 @@ def identity_answers a << [t("questions.name"), answers.full_name, "personal-details"] if show_name? a << [t("forms.address.questions.your_address"), answers.address, "address"] a << [t("questions.date_of_birth"), date_of_birth_string, "personal-details"] if show_dob? - a << [t("forms.gender.questions.payroll_gender"), t("answers.payroll_gender.#{answers.payroll_gender}"), "gender"] + a << payroll_gender a << [t("questions.teacher_reference_number"), answers.teacher_reference_number, "teacher-reference-number"] if show_trn? a << [t("questions.national_insurance_number"), answers.national_insurance_number, "personal-details"] if show_nino? a << [t("questions.email_address"), answers.email_address, "email-address"] unless show_email_select? @@ -68,5 +68,9 @@ def show_email_select? def show_mobile_select? answers.logged_in_with_tid? && answers.mobile_check.present? end + + def payroll_gender + [t("forms.gender.questions.payroll_gender"), t("answers.payroll_gender.#{answers.payroll_gender}"), "gender"] + end end end diff --git a/app/models/journeys/further_education_payments.rb b/app/models/journeys/further_education_payments.rb index 542c823edc..883ab5e307 100644 --- a/app/models/journeys/further_education_payments.rb +++ b/app/models/journeys/further_education_payments.rb @@ -16,13 +16,24 @@ module FurtherEducationPayments "fixed-term-contract" => FixedTermContractForm, "taught-at-least-one-term" => TaughtAtLeastOneTermForm, "teaching-hours-per-week" => TeachingHoursPerWeekForm, + "teaching-hours-per-week-next-term" => TeachingHoursPerWeekNextTermForm, "further-education-teaching-start-year" => FurtherEducationTeachingStartYearForm, "subjects-taught" => SubjectsTaughtForm, + "building-construction-courses" => BuildingConstructionCoursesForm, + "chemistry-courses" => ChemistryCoursesForm, + "computing-courses" => ComputingCoursesForm, + "early-years-courses" => EarlyYearsCoursesForm, + "engineering-manufacturing-courses" => EngineeringManufacturingCoursesForm, + "maths-courses" => MathsCoursesForm, + "physics-courses" => PhysicsCoursesForm, "teaching-qualification" => TeachingQualificationForm, "poor-performance" => PoorPerformanceForm, "check-your-answers" => CheckYourAnswersForm, "ineligible" => IneligibleForm, - "half-teaching-hours" => HalfTeachingHoursForm + "half-teaching-hours" => HalfTeachingHoursForm, + "hours-teaching-eligible-subjects" => HoursTeachingEligibleSubjectsForm, + "eligible" => EligibleForm, + "teacher-reference-number" => TeacherReferenceNumberForm } } end diff --git a/app/models/journeys/further_education_payments/answers_presenter.rb b/app/models/journeys/further_education_payments/answers_presenter.rb index dc190f684d..931a2e9a7b 100644 --- a/app/models/journeys/further_education_payments/answers_presenter.rb +++ b/app/models/journeys/further_education_payments/answers_presenter.rb @@ -29,6 +29,14 @@ def eligibility_answers private + def payroll_gender + [ + t("further_education_payments.forms.gender.questions.payroll_gender"), + t("answers.payroll_gender.#{answers.payroll_gender}"), + "gender" + ] + end + def teaching_responsibilities [ t("further_education_payments.forms.teaching_responsibilities.question"), diff --git a/app/models/journeys/further_education_payments/courses_helper.rb b/app/models/journeys/further_education_payments/courses_helper.rb new file mode 100644 index 0000000000..3f8adf7cb6 --- /dev/null +++ b/app/models/journeys/further_education_payments/courses_helper.rb @@ -0,0 +1,92 @@ +module Journeys + module FurtherEducationPayments + module CoursesHelper + include ActionView::Helpers::UrlHelper + include GovukVisuallyHiddenHelper + include GovukLinkHelper + + ALL_COURSE_FIELDS = %i[ + building_construction_courses + chemistry_courses + computing_courses + early_years_courses + engineering_manufacturing_courses + maths_courses + physics_courses + ].freeze + + ALL_SUBJECTS = ALL_COURSE_FIELDS.map { |course_field| course_field.to_s.gsub("_courses", "") }.freeze + + COURSE_DESCRIPTIONS_WITH_INLINE_LINKS = { + building_construction_courses: { + esfa_buildingconstruction: [ + "building and construction", + "https://www.qualifications.education.gov.uk/Search?Status=Approved&Level=0,1,2,3,4&Sub=7" + ], + level2_3_apprenticeship: [ + "construction and the built environment occupational route", + "https://occupational-maps.instituteforapprenticeships.org/maps/route/construction" + ] + }, + computing_courses: { + esfa_digitalpractitioners: [ + "digital technology for practitioners", + "https://www.qualifications.education.gov.uk/Search?Status=Approved&Level=0,1,2,3,4&Sub=23&PageSize=10&Sort=Status" + ], + esfa_digitalusers: [ + "digital technology for users", + "https://www.qualifications.education.gov.uk/Search?Status=Approved&Level=0,1,2,3,4&Sub=22&PageSize=10&Sort=Status" + ], + level2_3_apprenticeship: [ + "digital occupational route", + "https://occupational-maps.instituteforapprenticeships.org/maps/route/digital" + ] + }, + early_years_courses: { + coursetoeyq: [ + "early years qualification", + "https://www.gov.uk/government/publications/early-years-qualifications-achieved-in-england" + ] + }, + engineering_manufacturing_courses: { + esfa_engineering: [ + "engineering", + "https://www.qualifications.education.gov.uk/Search?Status=Approved&Level=0,1,2,3,4&Sub=13&PageSize=10&Sort=Status" + ], + esfa_manufacturing: [ + "manufacturing technologies", + "https://www.qualifications.education.gov.uk/Search?Status=Approved&Level=0,1,2,3,4&Sub=26&PageSize=10&Sort=Status" + ], + esfa_transportation: [ + "transportation operations and maintenance", + "https://www.qualifications.education.gov.uk/Search?Status=Approved&Level=0,1,2,3,4&Sub=47&PageSize=10&Sort=Status" + ], + level2_3_apprenticeship: [ + "engineering and manufacturing occupational route", + "https://occupational-maps.instituteforapprenticeships.org/maps/route/engineering-manufacturing" + ] + }, + maths_courses: { + esfa: [ + "mathematics and statistics", + "https://www.qualifications.education.gov.uk/Search?Status=Approved&Level=0,1,2,3,4&Sub=28&PageSize=10&Sort=Status" + ], + gcse_maths: [ + "other maths qualifications", + "https://submit-learner-data.service.gov.uk/find-a-learning-aim/LearningAimSearchResult?TeachingYear=2324&HasFilters=False&EFAFundingConditions=EFACONFUNDMATHS" + ] + } + }.freeze + + def course_option_description(course, opts = {}) + course_field = opts.key?(:i18n_form_namespace) ? opts[:i18n_form_namespace] : i18n_form_namespace + args = {i18n_form_namespace: course_field} + + text, url = COURSE_DESCRIPTIONS_WITH_INLINE_LINKS.dig(course_field.to_sym, course.to_sym) + args[:link] = govuk_link_to(text, url, new_tab: true) if text.present? && url.present? + + t("options.#{course}", args) + end + end + end +end diff --git a/app/models/journeys/further_education_payments/session_answers.rb b/app/models/journeys/further_education_payments/session_answers.rb index be5ff9f920..888e12fbbf 100644 --- a/app/models/journeys/further_education_payments/session_answers.rb +++ b/app/models/journeys/further_education_payments/session_answers.rb @@ -8,13 +8,26 @@ class SessionAnswers < Journeys::SessionAnswers attribute :fixed_term_full_year, :boolean attribute :taught_at_least_one_term, :boolean attribute :teaching_hours_per_week, :string + attribute :teaching_hours_per_week_next_term, :string attribute :further_education_teaching_start_year, :string attribute :subjects_taught, default: [] + attribute :building_construction_courses, default: [] + attribute :chemistry_courses, default: [] + attribute :computing_courses, default: [] + attribute :early_years_courses, default: [] + attribute :engineering_manufacturing_courses, default: [] + attribute :maths_courses, default: [] + attribute :physics_courses, default: [] + attribute :hours_teaching_eligible_subjects, :boolean attribute :teaching_qualification, :string attribute :subject_to_formal_performance_action, :boolean attribute :subject_to_disciplinary_action, :boolean attribute :half_teaching_hours, :boolean + def policy + Policies::FurtherEducationPayments + end + def school @school ||= School.find(school_id) end @@ -34,6 +47,34 @@ def subject_to_formal_performance_action? def subject_to_disciplinary_action? !!subject_to_disciplinary_action end + + def recent_further_education_teacher? + !further_education_teaching_start_year&.start_with?("pre-") + end + + def teaching_less_than_2_5_hours_per_week? + teaching_hours_per_week == "less_than_2_5" + end + + def teaching_less_than_2_5_hours_per_week_next_term? + teaching_hours_per_week_next_term == "less_than_2_5" + end + + def subject_to_problematic_actions? + subject_to_formal_performance_action || subject_to_disciplinary_action + end + + def lacks_teacher_qualification_or_enrolment? + teaching_qualification == "no_not_planned" + end + + def less_than_half_hours_teaching_fe? + half_teaching_hours == false + end + + def hours_teaching_eligible_subjects? + !!hours_teaching_eligible_subjects + end end end end diff --git a/app/models/journeys/further_education_payments/slug_sequence.rb b/app/models/journeys/further_education_payments/slug_sequence.rb index c6273fff15..99a0ac9ced 100644 --- a/app/models/journeys/further_education_payments/slug_sequence.rb +++ b/app/models/journeys/further_education_payments/slug_sequence.rb @@ -9,23 +9,57 @@ class SlugSequence fixed-term-contract taught-at-least-one-term teaching-hours-per-week + teaching-hours-per-week-next-term further-education-teaching-start-year subjects-taught - building-and-construction-courses - teaching-courses + building-construction-courses + chemistry-courses + computing-courses + early-years-courses + engineering-manufacturing-courses + maths-courses + physics-courses + hours-teaching-eligible-subjects half-teaching-hours teaching-qualification poor-performance check-your-answers-part-one + eligible ] + PERSONAL_DETAILS_SLUGS = %w[ + one-login-placeholder + information-provided + personal-details + postcode-search + select-home-address + address + email-address + email-verification + provide-mobile-number + mobile-number + mobile-verification + ].freeze + + PAYMENT_DETAILS_SLUGS = %w[ + bank-or-building-society + personal-bank-account + building-society-account + gender + teacher-reference-number + ].freeze + RESULTS_SLUGS = %w[ check-your-answers - eligible ineligible ].freeze - SLUGS = ELIGIBILITY_SLUGS + RESULTS_SLUGS + SLUGS = ( + ELIGIBILITY_SLUGS + + PERSONAL_DETAILS_SLUGS + + PAYMENT_DETAILS_SLUGS + + RESULTS_SLUGS + ).freeze def self.start_page_url if Rails.env.production? @@ -48,6 +82,7 @@ def slugs if answers.contract_type == "permanent" sequence.delete("fixed-term-contract") sequence.delete("taught-at-least-one-term") + sequence.delete("teaching-hours-per-week-next-term") end if answers.contract_type == "variable_hours" @@ -57,6 +92,42 @@ def slugs if answers.fixed_term_full_year == true sequence.delete("taught-at-least-one-term") end + + if answers.subjects_taught.exclude?("building_construction") + sequence.delete("building-construction-courses") + end + + if answers.subjects_taught.exclude?("chemistry") + sequence.delete("chemistry-courses") + end + + if answers.subjects_taught.exclude?("computing") + sequence.delete("computing-courses") + end + + if answers.subjects_taught.exclude?("early_years") + sequence.delete("early-years-courses") + end + + if answers.subjects_taught.exclude?("engineering_manufacturing") + sequence.delete("engineering-manufacturing-courses") + end + + if answers.subjects_taught.exclude?("maths") + sequence.delete("maths-courses") + end + + if answers.subjects_taught.exclude?("physics") + sequence.delete("physics-courses") + end + + if answers.provide_mobile_number == false + sequence.delete("mobile-number") + sequence.delete("mobile-verification") + end + + sequence.delete("personal-bank-account") if answers.building_society? + sequence.delete("building-society-account") if answers.personal_bank_account? end end end diff --git a/app/models/journeys/get_a_teacher_relocation_payment/answers_presenter.rb b/app/models/journeys/get_a_teacher_relocation_payment/answers_presenter.rb index b338407226..ec332742d5 100644 --- a/app/models/journeys/get_a_teacher_relocation_payment/answers_presenter.rb +++ b/app/models/journeys/get_a_teacher_relocation_payment/answers_presenter.rb @@ -8,6 +8,7 @@ def eligibility_answers a << application_route a << state_funded_secondary_school a << current_school + a << school_headteacher_name a << contract_details a << start_date_details a << subject_details @@ -23,12 +24,6 @@ def identity_answers end end - def employment_answers - [].tap do |a| - a << school_headteacher_name - end - end - private def show_trn? diff --git a/app/models/journeys/get_a_teacher_relocation_payment/slug_sequence.rb b/app/models/journeys/get_a_teacher_relocation_payment/slug_sequence.rb index 4d35d01c86..3974c56afe 100644 --- a/app/models/journeys/get_a_teacher_relocation_payment/slug_sequence.rb +++ b/app/models/journeys/get_a_teacher_relocation_payment/slug_sequence.rb @@ -5,6 +5,7 @@ class SlugSequence "application-route", "state-funded-secondary-school", "current-school", + "headteacher-details", "contract-details", "start-date", "subject", @@ -16,7 +17,6 @@ class SlugSequence PERSONAL_DETAILS_SLUGS = [ "nationality", "passport-number", - "headteacher-details", "personal-details", "postcode-search", "select-home-address", diff --git a/app/models/policies/further_education_payments.rb b/app/models/policies/further_education_payments.rb index 66bbfe295f..d7a92a7960 100644 --- a/app/models/policies/further_education_payments.rb +++ b/app/models/policies/further_education_payments.rb @@ -2,7 +2,13 @@ module Policies module FurtherEducationPayments include BasePolicy extend self + # Percentage of claims to QA MIN_QA_THRESHOLD = 10 + + # TODO: This is needed once the reply-to email address has been added to Gov Notify + def notify_reply_to_id + nil + end end end diff --git a/app/models/policies/further_education_payments/policy_eligibility_checker.rb b/app/models/policies/further_education_payments/policy_eligibility_checker.rb index 942d260c2a..e18921cd46 100644 --- a/app/models/policies/further_education_payments/policy_eligibility_checker.rb +++ b/app/models/policies/further_education_payments/policy_eligibility_checker.rb @@ -24,6 +24,34 @@ def ineligibility_reason :lack_teaching_responsibilities elsif answers.taught_at_least_one_term == false :must_teach_at_least_one_term + elsif !answers.recent_further_education_teacher? + :must_be_recent_further_education_teacher + elsif answers.teaching_less_than_2_5_hours_per_week? + :teaching_less_than_2_5 + elsif answers.teaching_less_than_2_5_hours_per_week_next_term? + :teaching_less_than_2_5_next_term + elsif answers.subject_to_problematic_actions? + :subject_to_problematic_actions + elsif answers.lacks_teacher_qualification_or_enrolment? + :lacks_teacher_qualification_or_enrolment + elsif answers.less_than_half_hours_teaching_fe? + :must_at_least_half_hours_teaching_fe + elsif answers.subjects_taught.include? "none" + :subject + elsif all_selected_courses_ineligible? + :courses + end + end + + private + + def all_selected_courses_ineligible? + groups = answers.subjects_taught.reject { |e| e == "none" } + + return if groups.empty? + + groups.all? do |subject| + answers.public_send(:"#{subject}_courses").include?("none") end end end diff --git a/app/models/policies/international_relocation_payments.rb b/app/models/policies/international_relocation_payments.rb index b6d75d5aad..75641260c1 100644 --- a/app/models/policies/international_relocation_payments.rb +++ b/app/models/policies/international_relocation_payments.rb @@ -14,5 +14,9 @@ module InternationalRelocationPayments def notify_reply_to_id nil end + + def award_amount + 5_000 + end end end diff --git a/app/models/policies/international_relocation_payments/eligibility.rb b/app/models/policies/international_relocation_payments/eligibility.rb index b755ebb54f..bc0d6b1741 100644 --- a/app/models/policies/international_relocation_payments/eligibility.rb +++ b/app/models/policies/international_relocation_payments/eligibility.rb @@ -10,10 +10,6 @@ class Eligibility < ApplicationRecord attr_accessor :teacher_reference_number - def award_amount - 0 - end - def ineligible? false end diff --git a/app/models/policies/international_relocation_payments/eligibility_admin_answers_presenter.rb b/app/models/policies/international_relocation_payments/eligibility_admin_answers_presenter.rb index 977e4f6652..28bf1f8ee5 100644 --- a/app/models/policies/international_relocation_payments/eligibility_admin_answers_presenter.rb +++ b/app/models/policies/international_relocation_payments/eligibility_admin_answers_presenter.rb @@ -11,18 +11,80 @@ def initialize(eligibility) def answers [].tap do |a| + a << nationality + a << passport_number a << current_school + a << subject + a << school_headteacher_name + a << start_date + a << visa_type + a << date_of_entry end end private + def nationality + [ + admin_display_name("nationality"), + eligibility.nationality + ] + end + + def passport_number + [ + admin_display_name("passport_number"), + eligibility.passport_number + ] + end + def current_school [ translate("admin.current_school"), display_school(eligibility.current_school) ] end + + def subject + [ + admin_display_name("subject"), + eligibility.subject.capitalize + ] + end + + def school_headteacher_name + [ + admin_display_name("school_headteacher_name"), + eligibility.school_headteacher_name + ] + end + + def start_date + [ + admin_display_name("start_date"), + eligibility.start_date.strftime("%-d %B %Y") + ] + end + + def visa_type + [ + admin_display_name("visa_type"), + eligibility.visa_type + ] + end + + def date_of_entry + [ + admin_display_name("date_of_entry"), + eligibility.date_of_entry.strftime("%-d %B %Y") + ] + end + + def admin_display_name(attr) + translate( + "international_relocation_payments.admin.eligibility_answers.#{attr}" + ) + end end end end diff --git a/app/views/additional_payments/claims/check_your_answers.html.erb b/app/views/additional_payments/claims/check_your_answers.html.erb index 5c6d1cf68b..7761e08322 100644 --- a/app/views/additional_payments/claims/check_your_answers.html.erb +++ b/app/views/additional_payments/claims/check_your_answers.html.erb @@ -9,6 +9,7 @@
+ <%# Errors are from the SubmissionsController %> <% if @form.errors.any? %> <%= render("shared/error_summary", instance: @form) %> <% end %> diff --git a/app/views/admin/eligible_fe_providers/new.html.erb b/app/views/admin/eligible_fe_providers/new.html.erb new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/views/admin/journey_configurations/_edit_additional_payments.html.erb b/app/views/admin/journey_configurations/_edit_additional_payments.html.erb new file mode 100644 index 0000000000..b1c5857ce9 --- /dev/null +++ b/app/views/admin/journey_configurations/_edit_additional_payments.html.erb @@ -0,0 +1,59 @@ +
+ +
+
+

+ Download Levelling Up Premium Payments School Awards +

+ + <% if lupp_awards_academic_years.any? %> + <%= form_with model: [:admin, Policies::LevellingUpPremiumPayments::Award], method: :get, url: admin_levelling_up_premium_payments_awards_path do |form| %> +
+ + + <%= form.select :academic_year, lupp_awards_academic_years, {}, class: "govuk-select", id: "download_academic_year" %> + + <%= form.submit "Download CSV", class: "govuk-button", data: { module: "govuk-button" } %> +
+ <% end %> + <% else %> +

No school award data has been uploaded.

+ <% end %> +
+
+ +
+ +
+
+

+ Upload Levelling Up Premium Payments School Awards +

+ + <%= render("shared/error_summary", instance: @csv_upload) if @csv_upload.errors.any? %> + + <%= form_with model: @csv_upload, url: admin_levelling_up_premium_payments_awards_path, multipart: true do |form| %> + <%= form_group_tag @csv_upload, :academic_year do %> + + + <%= form.select :academic_year, options_for_academic_year, {}, class: "govuk-select", id: "upload_academic_year" %> + <% end %> + + <%= form_group_tag @csv_upload, :csv_data do %> + <%= errors_tag @csv_upload, :csv_data %> + + <%= form.label :csv_data, "CSV file", class: "govuk-label" %> + + <%= form.file_field :csv_data, class: "govuk-file-upload#{" govuk-file-upload--error" if @csv_upload&.errors[:csv_data]&.any?}" %> + <% end %> + +
+ <%= form.submit "Upload CSV", class: "govuk-button", data: { module: "govuk-button" } %> +
+ <% end %> +
+
diff --git a/app/views/admin/journey_configurations/_edit_further_education_payments.html.erb b/app/views/admin/journey_configurations/_edit_further_education_payments.html.erb new file mode 100644 index 0000000000..3a83b6cd05 --- /dev/null +++ b/app/views/admin/journey_configurations/_edit_further_education_payments.html.erb @@ -0,0 +1,33 @@ +
+ +

+ Download eligible FE providers +

+ +<%= form_with model: @download_form, scope: :eligible_fe_providers_download, url: admin_eligible_fe_providers_path, builder: GOVUKDesignSystemFormBuilder::FormBuilder, method: :get do |f| %> + <%= f.govuk_error_summary %> + + <%= f.govuk_collection_select :academic_year, f.object.select_options, :id, :name, + label: { text: "Academic year" } %> + + <%= f.govuk_submit "Download CSV" %> +<% end %> + +
+ +

+ Upload eligible FE providers +

+ +<%= form_with model: @upload_form, scope: :eligible_fe_providers_upload, url: admin_eligible_fe_providers_path, builder: GOVUKDesignSystemFormBuilder::FormBuilder do |f| %> + <%= f.govuk_error_summary %> + + <%= f.govuk_collection_select :academic_year, f.object.select_options, :id, :name, + label: { text: "Academic year" } %> + + <%= f.govuk_file_field :file, + label: { text: "Eligible FE providers" }, + hint: { text: "This file should be a CSV" } %> + + <%= f.govuk_submit "Upload CSV" %> +<% end %> diff --git a/app/views/admin/journey_configurations/edit.html.erb b/app/views/admin/journey_configurations/edit.html.erb index a0ae400e83..d1fdfde33d 100644 --- a/app/views/admin/journey_configurations/edit.html.erb +++ b/app/views/admin/journey_configurations/edit.html.erb @@ -1,5 +1,9 @@ <% content_for(:page_title) { page_title("Manage #{journey_service_name(journey_configuration.journey::ROUTING_NAME)}") } %> +<% content_for :back_link do %> + <%= govuk_back_link href: admin_journey_configurations_path %> +<% end %> +

@@ -99,64 +103,6 @@

-
- -<% if journey_configuration.additional_payments? %> -
-
-

- Download Levelling Up Premium Payments School Awards -

- - <% if lupp_awards_academic_years.any? %> - <%= form_with model: [:admin, Policies::LevellingUpPremiumPayments::Award], method: :get, url: admin_levelling_up_premium_payments_awards_path do |form| %> -
- - - <%= form.select :academic_year, lupp_awards_academic_years, {}, class: "govuk-select", id: "download_academic_year" %> - - <%= form.submit "Download CSV", class: "govuk-button", data: { module: "govuk-button" } %> -
- <% end %> - <% else %> -

No school award data has been uploaded.

- <% end %> -
-
- -
- -
-
-

- Upload Levelling Up Premium Payments School Awards -

- - <%= render("shared/error_summary", instance: @csv_upload) if @csv_upload.errors.any? %> - - <%= form_with model: @csv_upload, url: admin_levelling_up_premium_payments_awards_path, multipart: true do |form| %> - <%= form_group_tag @csv_upload, :academic_year do %> - - - <%= form.select :academic_year, options_for_academic_year, {}, class: "govuk-select", id: "upload_academic_year" %> - <% end %> - - <%= form_group_tag @csv_upload, :csv_data do %> - <%= errors_tag @csv_upload, :csv_data %> - - <%= form.label :csv_data, "CSV file", class: "govuk-label" %> - - <%= form.file_field :csv_data, class: "govuk-file-upload#{" govuk-file-upload--error" if @csv_upload&.errors[:csv_data]&.any?}" %> - <% end %> - -
- <%= form.submit "Upload CSV", class: "govuk-button", data: { module: "govuk-button" } %> -
- <% end %> -
-
+<% if lookup_context.exists?("admin/journey_configurations/_edit_#{journey_configuration.routing_name.underscore}") %> + <%= render partial: "admin/journey_configurations/edit_#{journey_configuration.routing_name.underscore}" %> <% end %> diff --git a/app/views/claims/gender.html.erb b/app/views/claims/gender.html.erb index f1458b1ec3..b90844fb2f 100644 --- a/app/views/claims/gender.html.erb +++ b/app/views/claims/gender.html.erb @@ -8,7 +8,7 @@ <%= f.govuk_radio_buttons_fieldset( :payroll_gender, legend: { - text: t("forms.gender.questions.payroll_gender"), + text: @form.t("questions.payroll_gender"), tag: "h1", size: "l" }, diff --git a/app/views/claims/information_provided.html.erb b/app/views/claims/information_provided.html.erb index 9e6618189e..84ffd658c7 100644 --- a/app/views/claims/information_provided.html.erb +++ b/app/views/claims/information_provided.html.erb @@ -79,6 +79,6 @@ <%= information_provided_further_details_with_link(policy: journey_session.answers.selected_claim_policy) %>

- <%= button_to "Continue", claim_path(current_journey_routing_name), method: :patch, class: "govuk-button", role: :button, data: { module: "govuk-button" } %> + <%= govuk_button_to "Continue", claim_path(current_journey_routing_name), method: :patch %>
diff --git a/app/views/claims/teacher_reference_number.html.erb b/app/views/claims/teacher_reference_number.html.erb index 1674f9c907..d9eefae65e 100644 --- a/app/views/claims/teacher_reference_number.html.erb +++ b/app/views/claims/teacher_reference_number.html.erb @@ -1,7 +1,7 @@ <% content_for( :page_title, page_title( - t("additional_payments.forms.teacher_reference_number.questions.teacher_reference_number"), + t("questions.teacher_reference_number"), journey: current_journey_routing_name, show_error: @form.errors.any?) ) %> @@ -16,7 +16,7 @@ spellcheck: "false", autocomplete: "off", label: { - text: t("additional_payments.forms.teacher_reference_number.questions.teacher_reference_number"), + text: t("questions.teacher_reference_number"), tag: "h1", size: "l" }, diff --git a/app/views/further_education_payments/claims/_courses.html.erb b/app/views/further_education_payments/claims/_courses.html.erb new file mode 100644 index 0000000000..6c835b6baf --- /dev/null +++ b/app/views/further_education_payments/claims/_courses.html.erb @@ -0,0 +1,38 @@ +<% content_for(:page_title, page_title(@form.t(:question), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> + +
+
+ <%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> + <%= f.govuk_error_summary %> + + <%= f.govuk_check_boxes_fieldset @form.course_field, + legend: { + text: @form.t(:question), + tag: "h1", + size: "l" + }, + hint: { + text: @form.t(:hint, email: govuk_link_to(t("support_email_address", scope: @form.i18n_namespace))).html_safe + } do %> + <% @form.checkbox_options[0..-2].each do |option| %> + <%= f.govuk_check_box @form.course_field, option.id, + link_errors: @form.checkbox_options.first == option, + label: { + text: option.name.html_safe + } %> + <% end %> + + <%= f.govuk_check_box_divider %> + + <% option = @form.checkbox_options.last %> + <%= f.govuk_check_box @form.course_field, option.id, + exclusive: true, + label: { + text: option.name.html_safe + } %> + <% end %> + + <%= f.govuk_submit %> + <% end %> +
+
diff --git a/app/views/further_education_payments/claims/_ineligible_courses.html.erb b/app/views/further_education_payments/claims/_ineligible_courses.html.erb new file mode 100644 index 0000000000..1acd157d22 --- /dev/null +++ b/app/views/further_education_payments/claims/_ineligible_courses.html.erb @@ -0,0 +1,19 @@ +
+
+

+ You are not eligible +

+ +

+ In order to claim a levelling up premium payment, you must teach an <%= govuk_link_to "eligible FE course", "https://www.gov.uk/guidance/levelling-up-premium-payments-for-fe-teachers#eligible-fe-courses", new_tab: true %>. +

+ +

+ For more information, check the eligibility criteria for <%= govuk_link_to "levelling up premium payments for early career further education teachers", "https://www.gov.uk/guidance/levelling-up-premium-payments-for-fe-teachers", new_tab: true %>. +

+ +

+ The information entered is not stored. If you are unsure your information is correct, <%= govuk_link_to "start again", claim_path(current_journey_routing_name, "landing-page") %>. +

+
+
diff --git a/app/views/further_education_payments/claims/_ineligible_lack_teaching_responsibilities.html.erb b/app/views/further_education_payments/claims/_ineligible_lack_teaching_responsibilities.html.erb index e22255f18a..25ba2ee545 100644 --- a/app/views/further_education_payments/claims/_ineligible_lack_teaching_responsibilities.html.erb +++ b/app/views/further_education_payments/claims/_ineligible_lack_teaching_responsibilities.html.erb @@ -13,7 +13,7 @@

- The information entered is not stored. If you are unsure your information is correct, <%= govuk_link_to "start again", claim_path(current_journey_routing_name, "claim") %>. + The information entered is not stored. If you are unsure your information is correct, <%= govuk_link_to "start again", claim_path(current_journey_routing_name, "landing-page") %>.

diff --git a/app/views/further_education_payments/claims/_ineligible_lacks_teacher_qualification_or_enrolment.html.erb b/app/views/further_education_payments/claims/_ineligible_lacks_teacher_qualification_or_enrolment.html.erb new file mode 100644 index 0000000000..f438d23af1 --- /dev/null +++ b/app/views/further_education_payments/claims/_ineligible_lacks_teacher_qualification_or_enrolment.html.erb @@ -0,0 +1,25 @@ +
+
+

+ You are not eligible +

+ +

+ In order to claim an incentive payment, you must: +

+ + <%= govuk_list [ + "have a teaching qualification", + "be enrolled on a teaching qualification and working towards completing it", + "plan to enrol on a teaching qualification in the next 12 months" + ], type: :bullet %> + +

+ For more information, check the eligibility criteria for <%= govuk_link_to "levelling up premium payments for early career further education teachers", "https://www.gov.uk/guidance/levelling-up-premium-payments-for-fe-teachers", new_tab: true %>. +

+ +

+ The information entered is not stored. If you are unsure your information is correct, <%= govuk_link_to "start again", claim_path(current_journey_routing_name, "landing-page") %>. +

+
+
diff --git a/app/views/further_education_payments/claims/_ineligible_must_at_least_half_hours_teaching_fe.html.erb b/app/views/further_education_payments/claims/_ineligible_must_at_least_half_hours_teaching_fe.html.erb new file mode 100644 index 0000000000..4012f453b2 --- /dev/null +++ b/app/views/further_education_payments/claims/_ineligible_must_at_least_half_hours_teaching_fe.html.erb @@ -0,0 +1,24 @@ +
+
+

+ You are not eligible +

+ +

+ In order to claim a financial incentive payment, half of your timetabled teaching hours must include: +

+ + <%= govuk_list [ + "a student aged 16 to 19", + "a person up to age 25 with an Education, Health and Care Plan (EHCP)", + ], type: :bullet %> + +

+ For more information, check the eligibility criteria for <%= govuk_link_to "levelling up premium payments for early career further education teachers", "https://www.gov.uk/guidance/levelling-up-premium-payments-for-fe-teachers", new_tab: true %>. +

+ +

+ The information entered is not stored. If you are unsure your information is correct, <%= govuk_link_to "start again", claim_path(current_journey_routing_name, "landing-page") %>. +

+
+
diff --git a/app/views/further_education_payments/claims/_ineligible_must_be_recent_further_education_teacher.html.erb b/app/views/further_education_payments/claims/_ineligible_must_be_recent_further_education_teacher.html.erb new file mode 100644 index 0000000000..79387388fc --- /dev/null +++ b/app/views/further_education_payments/claims/_ineligible_must_be_recent_further_education_teacher.html.erb @@ -0,0 +1,19 @@ +
+
+

+ You are not eligible +

+ +

+ In order to claim a financial incentive payment, you must be in the first 5 years of your further education teaching career in England. +

+ +

+ For more information, check the eligibility criteria for <%= govuk_link_to "levelling up premium payments for early career further education teachers", "https://www.gov.uk/guidance/levelling-up-premium-payments-for-fe-teachers", new_tab: true %>. +

+ +

+ The information entered is not stored. If you are unsure your information is correct, <%= govuk_link_to "start again", claim_path(current_journey_routing_name, "landing-page") %>. +

+
+
diff --git a/app/views/further_education_payments/claims/_ineligible_subject.html.erb b/app/views/further_education_payments/claims/_ineligible_subject.html.erb new file mode 100644 index 0000000000..b5234d2e4f --- /dev/null +++ b/app/views/further_education_payments/claims/_ineligible_subject.html.erb @@ -0,0 +1,19 @@ +
+
+

+ You are not eligible +

+ +

+ In order to claim a levelling up premium payment, you must teach an <%= govuk_link_to "eligible FE subject", "https://www.gov.uk/guidance/levelling-up-premium-payments-for-fe-teachers#eligible-fe-courses", new_tab: true %>. +

+ +

+ For more information, check the eligibility criteria for <%= govuk_link_to "levelling up premium payments for early career further education teachers", "https://www.gov.uk/guidance/levelling-up-premium-payments-for-fe-teachers", new_tab: true %>. +

+ +

+ The information entered is not stored. If you are unsure your information is correct, <%= govuk_link_to "start again", claim_path(current_journey_routing_name, "landing-page") %>. +

+
+
diff --git a/app/views/further_education_payments/claims/_ineligible_subject_to_problematic_actions.html.erb b/app/views/further_education_payments/claims/_ineligible_subject_to_problematic_actions.html.erb new file mode 100644 index 0000000000..1d2f034be0 --- /dev/null +++ b/app/views/further_education_payments/claims/_ineligible_subject_to_problematic_actions.html.erb @@ -0,0 +1,25 @@ +
+
+

+ You are not eligible +

+ +

+ In order to claim an incentive payment, you must not currently be subject to any: +

+ + <%= govuk_list [ + "formal performance measures as a result of continuous poor teaching standards", + "disciplinary action" + ], + type: :bullet %> + +

+ For more information, check the eligibility criteria for <%= govuk_link_to "levelling up premium payments for early career further education teachers", "https://www.gov.uk/guidance/levelling-up-premium-payments-for-fe-teachers", new_tab: true %>. +

+ +

+ The information entered is not stored. If you are unsure your information is correct, <%= govuk_link_to "start again", claim_path(current_journey_routing_name, "landing-page") %>. +

+
+
diff --git a/app/views/further_education_payments/claims/_ineligible_teaching_less_than_2_5.html.erb b/app/views/further_education_payments/claims/_ineligible_teaching_less_than_2_5.html.erb new file mode 100644 index 0000000000..e19663c82c --- /dev/null +++ b/app/views/further_education_payments/claims/_ineligible_teaching_less_than_2_5.html.erb @@ -0,0 +1,19 @@ +
+
+

+ You are not eligible +

+ +

+ In order to claim an incentive payment, you must be timetabled to teach at least 2.5 hours per week in the current term. +

+ +

+ For more information, check the eligibility criteria for <%= govuk_link_to "levelling up premium payments for early career further education teachers", "https://www.gov.uk/guidance/levelling-up-premium-payments-for-fe-teachers", new_tab: true %>. +

+ +

+ The information entered is not stored. If you are unsure your information is correct, <%= govuk_link_to "start again", claim_path(current_journey_routing_name, "landing-page") %>. +

+
+
diff --git a/app/views/further_education_payments/claims/_ineligible_teaching_less_than_2_5_next_term.html.erb b/app/views/further_education_payments/claims/_ineligible_teaching_less_than_2_5_next_term.html.erb new file mode 100644 index 0000000000..de0d2534f2 --- /dev/null +++ b/app/views/further_education_payments/claims/_ineligible_teaching_less_than_2_5_next_term.html.erb @@ -0,0 +1,19 @@ +
+
+

+ <%= @form.t("#{@form.journey_eligibility_checker.ineligibility_reason}.heading") %> +

+ +

+ In order to claim an incentive payment, you must have an ongoing commitment to teach at least 2.5 hours per week next term. +

+ +

+ For more information, check the eligibility criteria for <%= govuk_link_to "levelling up premium payments for early career further education teachers", "https://www.gov.uk/guidance/levelling-up-premium-payments-for-fe-teachers", new_tab: true %>. +

+ +

+ The information entered is not stored. If you are unsure your information is correct, <%= govuk_link_to "start again", claim_path(current_journey_routing_name, "landing-page") %>. +

+
+
diff --git a/app/views/further_education_payments/claims/building_and_construction_courses.html.erb b/app/views/further_education_payments/claims/building_and_construction_courses.html.erb deleted file mode 100644 index 7bd7302159..0000000000 --- a/app/views/further_education_payments/claims/building_and_construction_courses.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -

- FE building and construction courses goes here -

- -<%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> - <%= f.govuk_submit %> -<% end %> diff --git a/app/views/further_education_payments/claims/building_construction_courses.html.erb b/app/views/further_education_payments/claims/building_construction_courses.html.erb new file mode 100644 index 0000000000..72fd5d68a1 --- /dev/null +++ b/app/views/further_education_payments/claims/building_construction_courses.html.erb @@ -0,0 +1 @@ +<%= render "courses" %> diff --git a/app/views/further_education_payments/claims/check_your_answers.html.erb b/app/views/further_education_payments/claims/check_your_answers.html.erb index 4cfef0b5be..b860ff89e4 100644 --- a/app/views/further_education_payments/claims/check_your_answers.html.erb +++ b/app/views/further_education_payments/claims/check_your_answers.html.erb @@ -1,7 +1,35 @@ -

- FE check your answers goes here -

+<% content_for( + :page_title, + page_title( + "Check your answers before sending your application", + journey: current_journey_routing_name, + show_error: @form.errors.any? + ) +) %> -<%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> - <%= f.govuk_submit %> -<% end %> +
+
+ <%# Errors are from the SubmissionsController %> + <% if @form.errors.any? %> + <%= render("shared/error_summary", instance: @form) %> + <% end %> + +

+ Check your answers before sending your application +

+ + <%= render partial: "claims/check_your_answers_section", locals: {heading: "Identity details", answers: journey.answers_for_claim(@form.journey_session).identity_answers} %> + + <%= render partial: "claims/check_your_answers_section", locals: {heading: "Payment details", answers: journey.answers_for_claim(@form.journey_session).payment_answers} %> + + <%= form_with url: claim_submission_path do |form| %> +

<%= t("further_education_payments.check_your_answers.heading_send_application") %>

+ +

<%= t("further_education_payments.check_your_answers.statement") %>

+ +
+ <%= form.submit t("further_education_payments.check_your_answers.btn_text"), class: "govuk-button" %> +
+ <% end %> +
+
diff --git a/app/views/further_education_payments/claims/chemistry_courses.html.erb b/app/views/further_education_payments/claims/chemistry_courses.html.erb new file mode 100644 index 0000000000..72fd5d68a1 --- /dev/null +++ b/app/views/further_education_payments/claims/chemistry_courses.html.erb @@ -0,0 +1 @@ +<%= render "courses" %> diff --git a/app/views/further_education_payments/claims/computing_courses.html.erb b/app/views/further_education_payments/claims/computing_courses.html.erb new file mode 100644 index 0000000000..72fd5d68a1 --- /dev/null +++ b/app/views/further_education_payments/claims/computing_courses.html.erb @@ -0,0 +1 @@ +<%= render "courses" %> diff --git a/app/views/further_education_payments/claims/contract_type.html.erb b/app/views/further_education_payments/claims/contract_type.html.erb index 6da1881189..071269a7e8 100644 --- a/app/views/further_education_payments/claims/contract_type.html.erb +++ b/app/views/further_education_payments/claims/contract_type.html.erb @@ -1,12 +1,18 @@ -<%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> - <%= f.govuk_error_summary %> +<% content_for(:page_title, page_title(@form.t(:question, school_name: journey_session.answers.school.name), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> - <%= f.govuk_collection_radio_buttons :contract_type, @form.radio_options, :id, :name, :hint, - legend: { - text: @form.t(:question, school_name: journey_session.answers.school.name), - tag: "h1", - size: "l" - } %> +
+
+ <%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> + <%= f.govuk_error_summary %> - <%= f.govuk_submit %> -<% end %> + <%= f.govuk_collection_radio_buttons :contract_type, @form.radio_options, :id, :name, :hint, + legend: { + text: @form.t(:question, school_name: journey_session.answers.school.name), + tag: "h1", + size: "l" + } %> + + <%= f.govuk_submit %> + <% end %> +
+
diff --git a/app/views/further_education_payments/claims/early_years_courses.html.erb b/app/views/further_education_payments/claims/early_years_courses.html.erb new file mode 100644 index 0000000000..72fd5d68a1 --- /dev/null +++ b/app/views/further_education_payments/claims/early_years_courses.html.erb @@ -0,0 +1 @@ +<%= render "courses" %> diff --git a/app/views/further_education_payments/claims/eligible.html.erb b/app/views/further_education_payments/claims/eligible.html.erb index 9a1a8936d9..c992d31013 100644 --- a/app/views/further_education_payments/claims/eligible.html.erb +++ b/app/views/further_education_payments/claims/eligible.html.erb @@ -1,8 +1,10 @@ +<% content_for(:page_title, page_title(@form.t(:heading), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> +
<%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> <%= govuk_panel( - title_text: "You’re eligible for a financial incentive payment", + title_text: @form.t(:heading), html_attributes: { class: "govuk-panel--informational" } diff --git a/app/views/further_education_payments/claims/engineering_manufacturing_courses.html.erb b/app/views/further_education_payments/claims/engineering_manufacturing_courses.html.erb new file mode 100644 index 0000000000..72fd5d68a1 --- /dev/null +++ b/app/views/further_education_payments/claims/engineering_manufacturing_courses.html.erb @@ -0,0 +1 @@ +<%= render "courses" %> diff --git a/app/views/further_education_payments/claims/fixed_term_contract.html.erb b/app/views/further_education_payments/claims/fixed_term_contract.html.erb index fc16c09e1f..f7a2ff8dcb 100644 --- a/app/views/further_education_payments/claims/fixed_term_contract.html.erb +++ b/app/views/further_education_payments/claims/fixed_term_contract.html.erb @@ -1,3 +1,5 @@ +<% content_for(:page_title, page_title(@form.t(:question, academic_year: @form.current_academic_year.to_s(:long)), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> +
<%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> diff --git a/app/views/further_education_payments/claims/further_education_provision_search.html.erb b/app/views/further_education_payments/claims/further_education_provision_search.html.erb index a814e016be..26b68aa245 100644 --- a/app/views/further_education_payments/claims/further_education_provision_search.html.erb +++ b/app/views/further_education_payments/claims/further_education_provision_search.html.erb @@ -1,3 +1,5 @@ +<% content_for(:page_title, page_title(@form.t(:question), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> +
<%= form_with model: @form, diff --git a/app/views/further_education_payments/claims/further_education_teaching_start_year.html.erb b/app/views/further_education_payments/claims/further_education_teaching_start_year.html.erb index 1c12135be6..94474062b2 100644 --- a/app/views/further_education_payments/claims/further_education_teaching_start_year.html.erb +++ b/app/views/further_education_payments/claims/further_education_teaching_start_year.html.erb @@ -1,3 +1,5 @@ +<% content_for(:page_title, page_title(@form.t(:question), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> +
<%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> diff --git a/app/views/further_education_payments/claims/half_teaching_hours.html.erb b/app/views/further_education_payments/claims/half_teaching_hours.html.erb index 1767eee6ab..f0778e7ba5 100644 --- a/app/views/further_education_payments/claims/half_teaching_hours.html.erb +++ b/app/views/further_education_payments/claims/half_teaching_hours.html.erb @@ -1,3 +1,5 @@ +<% content_for(:page_title, page_title(@form.t(:question), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> +
<%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> diff --git a/app/views/further_education_payments/claims/hours_teaching_eligible_subjects.html.erb b/app/views/further_education_payments/claims/hours_teaching_eligible_subjects.html.erb new file mode 100644 index 0000000000..2bc6951210 --- /dev/null +++ b/app/views/further_education_payments/claims/hours_teaching_eligible_subjects.html.erb @@ -0,0 +1,21 @@ +
+
+ <%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> + <%= f.govuk_error_summary %> + +

+ <%= @form.t(:question) %> +

+ +

+ At least 50% of your timetabled teaching hours must be spent teaching students of all ages in the following courses: +

+ + <%= govuk_list @form.courses, type: :bullet %> + + <%= f.govuk_collection_radio_buttons :hours_teaching_eligible_subjects, @form.radio_options, :id, :name, legend: { hidden: true } %> + + <%= f.govuk_submit %> + <% end %> +
+
diff --git a/app/views/further_education_payments/claims/ineligible.html.erb b/app/views/further_education_payments/claims/ineligible.html.erb index d95a12b23f..a4937bcb7b 100644 --- a/app/views/further_education_payments/claims/ineligible.html.erb +++ b/app/views/further_education_payments/claims/ineligible.html.erb @@ -1 +1,3 @@ +<% content_for(:page_title, page_title(@form.t("#{@form.journey_eligibility_checker.ineligibility_reason}.heading"), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> + <%= render "ineligible_#{@form.journey_eligibility_checker.ineligibility_reason}" %> diff --git a/app/views/further_education_payments/claims/information_provided.html.erb b/app/views/further_education_payments/claims/information_provided.html.erb new file mode 100644 index 0000000000..206e82c4f4 --- /dev/null +++ b/app/views/further_education_payments/claims/information_provided.html.erb @@ -0,0 +1,78 @@ +<% content_for(:page_title, page_title("How we will use the information you provide", journey: current_journey_routing_name)) %> + +
+
+

How we will use the information you provide in your application

+ +

To process your application

+ +

+ We will check the information you have provided with the further education provider where you currently teach. +

+ +

+ We may also check this information with: +

+ + <%= govuk_list [ + "the Department for Education’s (DfE) database of qualified teachers", + "the Teacher Pension Scheme" + ], type: :bullet %> + +

To pay you

+ +

+ DfE will make the payment directly to you. +

+ +

+ To complete the rest of your application, you will need your: +

+ + <%= govuk_list [ + "National Insurance number", + "bank account details", + "anything else needed" + ], type: :bullet %> + +

+ You will also be asked to provide your teacher reference number (TRN) if you have one, although this is optional. +

+ + <%= govuk_details(summary_text: "Where can I find my TRN?") do %> +

+ Your TRN may be shown on a: +

+ + <%= govuk_list [ + "payslip", + "teacher pension statement", + "teacher training records" + ], type: :bullet %> + +

+ Get help to <%= govuk_link_to "find your TRN", "https://find-a-lost-trn.education.gov.uk/start", new_tab: true %> if you do not know it or have forgotten it. +

+ <% end %> + +

Student loan deductions

+ +

+ If you are currently paying off a student loan, a deduction from your payment will go towards repaying it. +

+ +

Income Tax

+ +

+ Your financial incentive payment is taxable income, but DfE will pay Income Tax and National Insurance contributions due to HMRC for you. + This means the payment amount you receive may be lower following tax deductions. +

+ +

+ For more details, you can read about payments and deductions for the + <%= govuk_link_to "levelling up premium payment", "https://www.gov.uk/guidance/levelling-up-premium-payments-for-fe-teachers", new_tab: true %>. +

+ + <%= govuk_button_to "Continue", claim_path(current_journey_routing_name), method: :patch %> +
+
diff --git a/app/views/further_education_payments/claims/maths_courses.html.erb b/app/views/further_education_payments/claims/maths_courses.html.erb new file mode 100644 index 0000000000..72fd5d68a1 --- /dev/null +++ b/app/views/further_education_payments/claims/maths_courses.html.erb @@ -0,0 +1 @@ +<%= render "courses" %> diff --git a/app/views/further_education_payments/claims/teaching_courses.html.erb b/app/views/further_education_payments/claims/one_login_placeholder.html.erb similarity index 88% rename from app/views/further_education_payments/claims/teaching_courses.html.erb rename to app/views/further_education_payments/claims/one_login_placeholder.html.erb index f6a61047d2..0e253179d2 100644 --- a/app/views/further_education_payments/claims/teaching_courses.html.erb +++ b/app/views/further_education_payments/claims/one_login_placeholder.html.erb @@ -1,5 +1,5 @@

- FE teaching courses goes here + FE ONE LOGIN PLACEHOLDER

<%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> diff --git a/app/views/further_education_payments/claims/physics_courses.html.erb b/app/views/further_education_payments/claims/physics_courses.html.erb new file mode 100644 index 0000000000..72fd5d68a1 --- /dev/null +++ b/app/views/further_education_payments/claims/physics_courses.html.erb @@ -0,0 +1 @@ +<%= render "courses" %> diff --git a/app/views/further_education_payments/claims/poor_performance.html.erb b/app/views/further_education_payments/claims/poor_performance.html.erb index 48323259eb..bbaacddfd6 100644 --- a/app/views/further_education_payments/claims/poor_performance.html.erb +++ b/app/views/further_education_payments/claims/poor_performance.html.erb @@ -1,3 +1,5 @@ +<% content_for(:page_title, page_title(@form.t(:heading), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> +
<%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> diff --git a/app/views/further_education_payments/claims/select_provision.html.erb b/app/views/further_education_payments/claims/select_provision.html.erb index 69b48e4bae..d9799df4e1 100644 --- a/app/views/further_education_payments/claims/select_provision.html.erb +++ b/app/views/further_education_payments/claims/select_provision.html.erb @@ -1,13 +1,19 @@ -<%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> - <%= f.govuk_error_summary %> +<% content_for(:page_title, page_title(@form.t(:heading), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> - <%= f.govuk_collection_radio_buttons :school_id, @form.radio_options, :id, :name, :address, - legend: { - text: "Select the college you teach at", - tag: "h1", - size: "l" - }, - hint: { text: "Select your college from the search results." } %> +
+
+ <%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> + <%= f.govuk_error_summary %> - <%= f.govuk_submit %> -<% end %> + <%= f.govuk_collection_radio_buttons :school_id, @form.radio_options, :id, :name, :address, + legend: { + text: @form.t("heading"), + tag: "h1", + size: "l" + }, + hint: { text: "Select your college from the search results." } %> + + <%= f.govuk_submit %> + <% end %> +
+
diff --git a/app/views/further_education_payments/claims/subjects_taught.html.erb b/app/views/further_education_payments/claims/subjects_taught.html.erb index 3a85dcbeae..b7f9a8d053 100644 --- a/app/views/further_education_payments/claims/subjects_taught.html.erb +++ b/app/views/further_education_payments/claims/subjects_taught.html.erb @@ -1,3 +1,5 @@ +<% content_for(:page_title, page_title(@form.t(:question), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> +
<%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> diff --git a/app/views/further_education_payments/claims/taught_at_least_one_term.html.erb b/app/views/further_education_payments/claims/taught_at_least_one_term.html.erb index 24d86e8af3..800a093d35 100644 --- a/app/views/further_education_payments/claims/taught_at_least_one_term.html.erb +++ b/app/views/further_education_payments/claims/taught_at_least_one_term.html.erb @@ -1,3 +1,5 @@ +<% content_for(:page_title, page_title(@form.t(:question, school_name: journey_session.answers.school.name), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> +
<%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> diff --git a/app/views/further_education_payments/claims/teaching_hours_per_week.html.erb b/app/views/further_education_payments/claims/teaching_hours_per_week.html.erb index f8592511e5..34421c391f 100644 --- a/app/views/further_education_payments/claims/teaching_hours_per_week.html.erb +++ b/app/views/further_education_payments/claims/teaching_hours_per_week.html.erb @@ -1,3 +1,5 @@ +<% content_for(:page_title, page_title(@form.t(:question, school_name: journey_session.answers.school.name), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> +
<%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> diff --git a/app/views/further_education_payments/claims/teaching_hours_per_week_next_term.html.erb b/app/views/further_education_payments/claims/teaching_hours_per_week_next_term.html.erb new file mode 100644 index 0000000000..2439b1d243 --- /dev/null +++ b/app/views/further_education_payments/claims/teaching_hours_per_week_next_term.html.erb @@ -0,0 +1,19 @@ +<% content_for(:page_title, page_title(@form.t(:question, school_name: journey_session.answers.school.name), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> + +
+
+ <%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> + <%= f.govuk_error_summary %> + + <%= f.govuk_collection_radio_buttons :teaching_hours_per_week_next_term, @form.radio_options, :id, :name, + legend: { + text: @form.t(:question, school_name: journey_session.answers.school.name), + tag: "h1", + size: "l" + }, + hint: { text: @form.t(:hint) } %> + + <%= f.govuk_submit %> + <% end %> +
+
diff --git a/app/views/further_education_payments/claims/teaching_qualification.html.erb b/app/views/further_education_payments/claims/teaching_qualification.html.erb index bcbdcae16d..8b7d2182cf 100644 --- a/app/views/further_education_payments/claims/teaching_qualification.html.erb +++ b/app/views/further_education_payments/claims/teaching_qualification.html.erb @@ -1,3 +1,5 @@ +<% content_for(:page_title, page_title(@form.t(:question), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> +
<%= form_with model: @form, url: claim_path(current_journey_routing_name), method: :patch, builder: GOVUKDesignSystemFormBuilder::FormBuilder, html: { novalidate: false } do |f| %> diff --git a/app/views/further_education_payments/claims/teaching_responsibilities.html.erb b/app/views/further_education_payments/claims/teaching_responsibilities.html.erb index 4c68310d01..02b3fd85a1 100644 --- a/app/views/further_education_payments/claims/teaching_responsibilities.html.erb +++ b/app/views/further_education_payments/claims/teaching_responsibilities.html.erb @@ -1,3 +1,5 @@ +<% content_for(:page_title, page_title(@form.t(:question), journey: current_journey_routing_name, show_error: @form.errors.any?)) %> + <% @backlink_path = landing_page_path %>
diff --git a/app/views/further_education_payments/submissions/show.html.erb b/app/views/further_education_payments/submissions/show.html.erb new file mode 100644 index 0000000000..15435147d2 --- /dev/null +++ b/app/views/further_education_payments/submissions/show.html.erb @@ -0,0 +1,21 @@ +<% content_for(:page_title, page_title("Claim submitted", journey: current_journey_routing_name)) %> + +
+
+ +
+

+ You applied for a further education financial incentive payment +

+ +
+ Your reference number
+ <%= submitted_claim.reference %> +
+
+ +

+ FE CONFIRMATION PLACEHOLDER +

+
+
diff --git a/app/views/get_a_teacher_relocation_payment/claims/check_your_answers.html.erb b/app/views/get_a_teacher_relocation_payment/claims/check_your_answers.html.erb index b611eb0d72..7ec5c0d37c 100644 --- a/app/views/get_a_teacher_relocation_payment/claims/check_your_answers.html.erb +++ b/app/views/get_a_teacher_relocation_payment/claims/check_your_answers.html.erb @@ -23,14 +23,6 @@ } ) %> - <%= render( - partial: "claims/check_your_answers_section", - locals: { - heading: "Employment information", - answers: journey.answers_for_claim(@form.journey_session).employment_answers - } - ) %> - <%= render( partial: "claims/check_your_answers_section", locals: { diff --git a/app/views/layouts/admin.html.erb b/app/views/layouts/admin.html.erb index d99568ace2..5fe6db0181 100644 --- a/app/views/layouts/admin.html.erb +++ b/app/views/layouts/admin.html.erb @@ -85,6 +85,8 @@
+ <%= content_for(:back_link) %> +
<% flash.each do |name, msg| %>
diff --git a/app/views/student_loans/claims/check_your_answers.html.erb b/app/views/student_loans/claims/check_your_answers.html.erb index 7f71d49975..722a961c1d 100644 --- a/app/views/student_loans/claims/check_your_answers.html.erb +++ b/app/views/student_loans/claims/check_your_answers.html.erb @@ -9,6 +9,7 @@
+ <%# Errors are from the SubmissionsController %> <% if @form.errors.any? %> <%= render("shared/error_summary", instance: @form) %> <% end %> diff --git a/bin/azure-console b/bin/azure-console index 061e883507..c3c60c7b2b 100755 --- a/bin/azure-console +++ b/bin/azure-console @@ -5,8 +5,16 @@ ENVIRONMENT_NAME=$1 case $ENVIRONMENT_NAME in "production") - SUBSCRIPTION_ID="88bd392f-df19-458b-a100-22b4429060ed" - RESOURCE_GROUP_PREFIX="s118p01" + SUBSCRIPTION="s189-teacher-services-cloud-production" + NAMESPACE="srtl-production" + ;; + "test") + SUBSCRIPTION="s189-teacher-services-cloud-test" + NAMESPACE="srtl-test" + ;; + review-*) + SUBSCRIPTION="s189-teacher-services-cloud-test" + NAMESPACE="srtl-development" ;; *) echo "Could not find a known environment with the name: $ENVIRONMENT_NAME" @@ -34,10 +42,12 @@ if ! az account show > /dev/null; then az login > /dev/null fi -echo "**********************************************************************************************************************" -echo "IMPORTANT: Accessing the $ENVIRONMENT_NAME console in this way is VERY risky and should only be done as a last resort" -echo "This should only be done in pairs, and mutating any live data is STRONGLY discouraged." -echo "**********************************************************************************************************************" +if [[ $ENVIRONMENT_NAME == "production" ]]; then + echo "**********************************************************************************************************************" + echo "IMPORTANT: Accessing the $ENVIRONMENT_NAME console in this way is VERY risky and should only be done as a last resort" + echo "This should only be done in pairs, and mutating any live data is STRONGLY discouraged." + echo "**********************************************************************************************************************" +fi echo @@ -45,13 +55,9 @@ read -p "Are you sure you want to continue? (y/n)" -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then - az account set --subscription "$SUBSCRIPTION_ID" - - az container exec \ - --name=$RESOURCE_GROUP_PREFIX-app-worker-aci \ - --resource-group=$RESOURCE_GROUP_PREFIX-app \ - --exec-command="/bin/bash" + az account set --subscription "$SUBSCRIPTION" + kubectl -n $NAMESPACE exec -it deployment/claim-additional-payments-for-teaching-"$ENVIRONMENT_NAME"-worker -- rails console --sandbox exit 0 else echo "Quitting" diff --git a/bin/start-worker b/bin/start-worker index 847fa25529..9c65825b26 100755 --- a/bin/start-worker +++ b/bin/start-worker @@ -1,6 +1,4 @@ #!/bin/bash echo "Starting workers..." -/filebeat/filebeat -c /filebeat/filebeat.yml \ - & bundle exec bin/delayed_job start -n "$WORKER_COUNT" \ - & tail -f "log/$RAILS_ENV.log" +bundle exec bin/delayed_job run -n "$WORKER_COUNT" diff --git a/config/analytics.yml b/config/analytics.yml index ac870d4222..fe83873084 100644 --- a/config/analytics.yml +++ b/config/analytics.yml @@ -271,3 +271,11 @@ shared: - created_at - updated_at - award_amount + :eligible_fe_providers: + - id + - ukprn + - academic_year + - max_award_amount + - lower_award_amount + - created_at + - updated_at diff --git a/config/environments/development.rb b/config/environments/development.rb index e98dbb2339..d7b3cb6f23 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -87,4 +87,9 @@ # Add '127.0.0.1 ecp.test' to your /etc/hosts to use this over localhost. # This allows you to use https://ecp.test:3000/ in your browser. config.hosts << "ecp.test" + + # https://technical-guidance.education.gov.uk/infrastructure/monitoring/logit/#ruby-on-rails + config.log_level = :debug # Or :info + config.log_format = :color # Console colorised non-json output + config.semantic_logger.backtrace_level = :debug # Show file and line number (expensive: not for production) end diff --git a/config/environments/production.rb b/config/environments/production.rb index 6574840857..21b9b7fd6d 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -47,8 +47,11 @@ # information to avoid inadvertent exposure of personally identifiable information (PII). config.log_level = :info - # Prepend all log lines with the following tags. - config.log_tags = [:request_id] + # https://technical-guidance.education.gov.uk/infrastructure/monitoring/logit/#ruby-on-rails + config.log_format = :json # For parsing in Logit + config.rails_semantic_logger.add_file_appender = false # Don't log to file + config.active_record.logger = nil # Don't log SQL + config.rails_semantic_logger.filter = proc { |log| log.name != "DfE::Analytics::SendEvents" } # Use a different cache store in production. # config.cache_store = :mem_cache_store @@ -89,16 +92,6 @@ # require "syslog/logger" # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name") - if ENV["RAILS_LOG_TO_STDOUT"].present? - logger = ActiveSupport::Logger.new($stdout) - logger.formatter = config.log_formatter - config.logger = ActiveSupport::TaggedLogging.new(logger) - - $stdout.sync = true - config.rails_semantic_logger.add_file_appender = false - config.semantic_logger.add_appender(io: $stdout, formatter: config.rails_semantic_logger.format) - end - # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false end diff --git a/config/initializers/semantic_logger.rb b/config/initializers/semantic_logger.rb index 96bd559173..97dcc7763f 100644 --- a/config/initializers/semantic_logger.rb +++ b/config/initializers/semantic_logger.rb @@ -1,3 +1,10 @@ +# https://technical-guidance.education.gov.uk/infrastructure/monitoring/logit/#ruby-on-rails Rails.application.configure do - config.semantic_logger.application = "Claim Additional Payments for Teaching" + config.semantic_logger.application = "" # This is added by logstash from its tags + config.log_tags = [:request_id] # Prepend all log lines with the following tags +end + +unless Rails.env.test? + SemanticLogger.add_appender(io: $stdout, level: Rails.application.config.log_level, formatter: Rails.application.config.log_format) + Rails.application.config.logger.info("Application logging to STDOUT") end diff --git a/config/locales/en.yml b/config/locales/en.yml index db4d0493e8..9d8d1eba0f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -201,6 +201,12 @@ en: address: "address" full_name: "Full name" forms: + teacher_reference_number: + questions: + teacher_reference_number: "What is your teacher reference number (TRN)?" + errors: + blank: "Enter your teacher reference number" + length: "Teacher reference number must be 7 digits long" gender: questions: payroll_gender: "How is your gender recorded on your school’s payroll system?" @@ -254,6 +260,21 @@ en: errors: select_email: Select an option to indicate whether the email is correct or not invalid_email: Invalid email address. Please select a different email address + email_address: + errors: + presence: "Enter an email address" + format: "Enter an email address in the correct format, like name@example.com" + length: "Email address must be 256 characters or less" + mobile_number: + errors: + invalid: "Enter a mobile number, like 07700 900 982 or +44 7700 900 982" + claim_submission: + errors: + email_verified: "You must verify your email address before you can submit your claim" + email_address: "Enter an email address" + ineligible: "You’re not eligible for this payment" + mobile_number_verified: "You must verify your mobile number before you can submit your claim" + already_submitted: "You have already submitted this claim" student_loans: forms: claim_school: @@ -264,13 +285,6 @@ en: enter_a_school_or_postcode: "Enter a school or postcode" select_a_school: "Select a school from the list or search again for a different school" school_not_found: "School not found" - claim_submission_form: - errors: - email_verified: "You must verify your email address before you can submit your claim" - email_address: "Enter an email address" - ineligible: "You’re not eligible for this payment" - mobile_number_verified: "You must verify your mobile number before you can submit your claim" - already_submitted: "You have already submitted this claim" current_school: questions: current_school_search: "Which school are you currently employed to teach at?" @@ -280,11 +294,6 @@ en: select_the_school_you_teach_at: "Select the school you teach at" the_selected_school_is_closed: "The selected school is closed" school_not_found: "School not found" - email_address: - errors: - presence: "Enter an email address" - format: "Enter an email address in the correct format, like name@example.com" - length: "Email address must be 256 characters or less" leadership_position: questions: leadership_position: "Were you employed in a leadership position between %{financial_year}?" @@ -294,9 +303,6 @@ en: leader role." errors: inclusion: "Select yes if you were employed in a leadership position" - mobile_number: - errors: - invalid: "Enter a mobile number, like 07700 900 982 or +44 7700 900 982" mostly_performed_leadership_duties: questions: mostly_performed_leadership_duties: @@ -346,12 +352,6 @@ en: select_which_school_currently: Select if you still work at %{school_name}, another school or no longer teach in England select_are_you_still_employed: Select yes if you are still employed to teach at a school in England - teacher_reference_number: - questions: - teacher_reference_number: "What is your teacher reference number (TRN)?" - errors: - blank: "Enter your teacher reference number" - length: "Teacher reference number must be 7 digits long" qualification_details: errors: qualifications_details_check: "Select yes if your qualification details are correct" @@ -415,13 +415,6 @@ en: confirmed their %{bank_or_building_society} details?" additional_payments: &additional_payments forms: - claim_submission_form: - errors: - email_verified: "You must verify your email address before you can submit your claim" - email_address: "Enter an email address" - ineligible: "You’re not eligible for this payment" - mobile_number_verified: "You must verify your mobile number before you can submit your claim" - already_submitted: "You have already submitted this claim" correct_school: questions: which_school: "Which school do you teach at?" @@ -434,18 +427,10 @@ en: select_the_school_you_teach_at: "Select the school you teach at" the_selected_school_is_closed: "The selected school is closed" school_not_found: "School not found" - email_address: - errors: - presence: "Enter an email address" - format: "Enter an email address in the correct format, like name@example.com" - length: "Email address must be 256 characters or less" email_verification: errors: one_time_password: invalid: An error occured while validating the passcode, please try generating a new one - mobile_number: - errors: - invalid: "Enter a mobile number, like 07700 900 982 or +44 7700 900 982" nqt_in_academic_year_after_itt: errors: inclusion: Select yes if you are currently teaching as a qualified teacher @@ -548,12 +533,6 @@ en: employed_as_supply_teacher: Are you currently employed as a supply teacher? errors: inclusion: Select yes if you are a supply teacher - teacher_reference_number: - questions: - teacher_reference_number: "What is your teacher reference number (TRN)?" - errors: - blank: "Enter your teacher reference number" - length: "Teacher reference number must be 7 digits long" teaching_subject_now: questions: teaching_subject_now: "Do you spend at least half of your contracted hours teaching eligible subjects?" @@ -786,7 +765,17 @@ en: policy_short_name: "International Relocation Payments" policy_acronym: "IRP" admin: + eligibility_answers: + nationality: "Nationality" + passport_number: "Passport number" + subject: "Subject" + school_headteacher_name: "School headteacher name" + start_date: "Contract start date" + visa_type: "Visa type" + date_of_entry: "Date of entry" task_questions: + matching_details: + title: "Is this claim still valid despite having matching details with other claims?" identity_confirmation: title: "Did %{claim_full_name} submit the claim?" visa: @@ -805,9 +794,29 @@ en: landing_page: Find out if you are eligible for any incentive payments for further education teachers claim_description: for further education payments journey_name: Claim incentive payments for further education teachers - feedback_email: "fe-levellingup.premiumpayments@education.gov.uk" - support_email_address: "fe-levellingup.premiumpayments@education.gov.uk" + feedback_email: "FE-Levellingup.PremiumPayments@education.gov.uk" + support_email_address: "FE-Levellingup.PremiumPayments@education.gov.uk" + claim_subject: "Further education payment" forms: + ineligible: + courses: + heading: You are not eligible + lack_teaching_responsibilities: + heading: You are not eligible + lacks_teacher_qualification_or_enrolment: + heading: You are not eligible + must_at_least_half_hours_teaching_fe: + heading: You are not eligible + must_be_recent_further_education_teacher: + heading: You are not eligible + must_teach_at_least_one_term: + heading: You are not eligible for a financial incentive payment yet + subject_to_problematic_actions: + heading: You are not eligible + ineligible_teaching_less_than_2_5: + heading: You are not eligible + teaching_less_than_2_5_next_term: + heading: You are not eligible teaching_responsibilities: question: Are you a member of staff with teaching responsibilities? errors: @@ -818,6 +827,7 @@ en: blank: Enter a college name or postcode min_length: Enter a college name or postcode that is at least 3 characters long select_provision: + heading: Select the college you teach at errors: blank: Select the college you teach at contract_type: @@ -851,6 +861,14 @@ en: less_than_2_5: Less than 2.5 hours per week errors: inclusion: Select how many hours per week you are timetabled to teach during the current term + teaching_hours_per_week_next_term: + question: Are you timetabled to teach at least 2.5 hours per week at %{school_name} next term? + hint: If you are unsure, you should speak to HR or apply when you know your arrangements for next term. + options: + at_least_2_5: Yes, I am timetabled to teach at least 2.5 hours per week at %{school_name} next term + less_than_2_5: No, I’m not timetabled to teach at least 2.5 hours per week at %{school_name} next term + errors: + inclusion: Select yes if you are timetabled to teach at least 2.5 hours next term otherwise select you are not further_education_teaching_start_year: question: Which academic year did you start teaching in further education (FE) in England? options: @@ -862,16 +880,89 @@ en: question: Which subject areas do you teach? hint: Select all that apply options: - building_and_construction: Building and construction + building_construction: Building and construction chemistry: Chemistry computing: Computing, including digital and ICT early_years: Early years - engineering_and_manufacturing: Engineering and manufacturing, including transport engineering and electronics - mathematics: Mathematics + engineering_manufacturing: Engineering and manufacturing, including transport engineering and electronics + maths: Maths physics: Physics none: I do not teach any of these subjects errors: inclusion: Select the subject areas you teach in or select you do not teach any of the listed subject areas + courses: &courses + hint: | +

If you are unsure whether the course(s) you teach is eligible, please email:
%{email}

+

Select all that apply

+ errors: + inclusion: Select all the courses you teach otherwise select you do not teach any of these courses + building_construction_courses: + <<: *courses + question: Which building and construction courses do you teach? + options: + esfa_buildingconstruction: ESFA-funded qualifications at level 3 and below in the %{link} sector subject area + tlevel_building: T Level in building services engineering for construction + tlevel_onsiteconstruction: T Level in onsite construction + tlevel_design_surveying: T Level in design, surveying and planning for construction + level2_3_apprenticeship: Level 2 or level 3 apprenticeships in the %{link} + none: I do not teach any of these courses + chemistry_courses: + <<: *courses + question: Which chemistry courses do you teach? + options: + alevel_chemistry: A or AS level chemistry + gcse_chemistry: GCSE chemistry + ib_certificate_chemistry: International baccalaureate middle years programme or certificate in chemistry + none: I do not teach any of these courses + computing_courses: + <<: *courses + question: Which computing courses do you teach? + options: + esfa_digitalpractitioners: ESFA-funded qualifications at level 3 and below in the %{link} sector subject area + esfa_digitalusers: ESFA-funded qualifications at level 3 and below in the %{link} sector subject area + digitalskills_quals: Digital functional skills qualifications and essential digital skills qualifications + tlevel_digitalsupport: T Level in digital support services + tlevel_digitalbusiness: T Level in digital business services + tlevel_digitalproduction: T Level in digital production, design and development + ib_certificate_compsci: International baccalaureate certificate in computer science + level2_3_apprenticeship: Level 2 or level 3 apprenticeships in the %{link} + none: I do not teach any of these courses + early_years_courses: + <<: *courses + question: Which early years courses do you teach? + options: + eylevel2: Early years practitioner (level 2) apprenticeship + eylevel3: Early years educator (level 3) apprenticeship + eytlevel: T Level in education and early years (early years educator) + coursetoeyq: A course that leads to an %{link} which enables providers to count the recipient in staff:child ratios + none: I do not teach any of these courses + engineering_manufacturing_courses: + <<: *courses + question: Which engineering and manufacturing courses do you teach? + options: + esfa_engineering: ESFA-funded qualifications at level 3 and below in the %{link} sector subject area + esfa_manufacturing: ESFA-funded qualifications at level 3 and below in the %{link} sector subject area + esfa_transportation: ESFA-funded qualifications at level 3 and below in the %{link} sector subject area + tlevel_design: T Level in design and development for engineering and manufacturing + tlevel_maintenance: T Level in maintenance, installation and repair for engineering and manufacturing + tlevel_engineering: T Level in engineering, manufacturing, processing and control + level2_3_apprenticeship: Level 2 or level 3 apprenticeships in the %{link} + none: I do not teach any of these courses + maths_courses: + <<: *courses + question: Which maths courses do you teach? + options: + esfa: ESFA-funded qualifications at level 3 and below in the %{link} sector subject area + gcse_maths: Maths GCSE, functional skills qualifications and %{link} approved for teaching to 16 to 19-year-olds who meet the condition of funding + none: I do not teach any of these courses + physics_courses: + <<: *courses + question: Which physics courses do you teach? + options: + alevel_physics: A or AS level physics + gcse_physics: GCSE physics + ib_certificate_physics: International baccalaureate middle years programme or certificate in physics + none: I do not teach any of these courses teaching_qualification: question: Do you have a teaching qualification? hint: Your response will be noted for future claims. If you don’t have a teaching qualification yet, make sure that you enrol on one or complete one in the next 12 months. @@ -900,10 +991,26 @@ en: question: Are at least half of your timetabled teaching hours spent teaching 16 to 19-year-olds, including those up to age 25 with an Education, Health and Care Plan (EHCP)? errors: inclusion: Select yes if at least half your timetabled teaching hours are spent teaching 16-19-year-olds, including those up to 25 with an Education, Health and Care Plan + eligible: + heading: You’re eligible for a financial incentive payment + gender: + questions: + payroll_gender: "How is your gender recorded on your employer’s payroll system?" + errors: + select_gender: "Select the gender recorded on your employer’s payroll system or select whether you do not know" + hours_teaching_eligible_subjects: + question: Do you spend at least half of your timetabled teaching hours teaching these eligible courses? + errors: + inclusion: Select yes if you spend at least half of your timetabled teaching hours teaching these eligible courses check_your_answers: part_one: primary_heading: Check your answers confirmation_notice: By selecting continue you are confirming that, to the best of your knowledge, the details you are providing are correct. + heading_send_application: Now send your application + statement: + By submitting this you are confirming that, to the best of your knowledge, the details you are providing are + correct. + btn_text: Accept and send activerecord: errors: models: diff --git a/config/routes.rb b/config/routes.rb index 4da66505fb..5e6f52161c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -119,6 +119,7 @@ def matches?(request) resources :journey_configurations, only: [:index, :edit, :update] resources :levelling_up_premium_payments_awards, only: [:index, :create] + resource :eligible_fe_providers, only: [:create, :show], path: "eligible-further-education-providers" get "refresh-session", to: "sessions#refresh", as: :refresh_session diff --git a/db/data/20240709134609_add_irp_journey_configuration.rb b/db/data/20240709134609_add_irp_journey_configuration.rb new file mode 100644 index 0000000000..4de8023067 --- /dev/null +++ b/db/data/20240709134609_add_irp_journey_configuration.rb @@ -0,0 +1,6 @@ +# Run me with `rails runner db/data/20240709134609_add_irp_journey_configuration.rb` + +Journeys::Configuration.create!( + routing_name: Journeys::GetATeacherRelocationPayment::ROUTING_NAME, + current_academic_year: AcademicYear.current +) diff --git a/db/migrate/20240709110147_add_award_amount_to_international_relocation_payments_eligibilities.rb b/db/migrate/20240709110147_add_award_amount_to_international_relocation_payments_eligibilities.rb new file mode 100644 index 0000000000..8f318d409b --- /dev/null +++ b/db/migrate/20240709110147_add_award_amount_to_international_relocation_payments_eligibilities.rb @@ -0,0 +1,5 @@ +class AddAwardAmountToInternationalRelocationPaymentsEligibilities < ActiveRecord::Migration[7.0] + def change + add_column :international_relocation_payments_eligibilities, :award_amount, :decimal, precision: 7, scale: 2 + end +end diff --git a/db/migrate/20240710080536_create_eligible_fe_providers.rb b/db/migrate/20240710080536_create_eligible_fe_providers.rb new file mode 100644 index 0000000000..85a94026a4 --- /dev/null +++ b/db/migrate/20240710080536_create_eligible_fe_providers.rb @@ -0,0 +1,14 @@ +class CreateEligibleFeProviders < ActiveRecord::Migration[7.0] + def change + create_table :eligible_fe_providers, id: :uuid do |t| + t.integer :ukprn, null: false + t.text :academic_year, limit: 9, null: false + t.decimal :max_award_amount, precision: 7, scale: 2 + t.decimal :lower_award_amount, precision: 7, scale: 2 + + t.timestamps + end + + add_index :eligible_fe_providers, [:academic_year, :ukprn] + end +end diff --git a/db/schema.rb b/db/schema.rb index 96d92f0c84..dd8e02e8db 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2024_07_02_105328) do +ActiveRecord::Schema[7.0].define(version: 2024_07_10_080536) do # These are extensions that must be enabled in order to support this database enable_extension "pg_trgm" enable_extension "pgcrypto" @@ -175,6 +175,16 @@ t.index ["teacher_reference_number"], name: "index_ecp_eligibility_trn" end + create_table "eligible_fe_providers", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "ukprn", null: false + t.text "academic_year", null: false + t.decimal "max_award_amount", precision: 7, scale: 2 + t.decimal "lower_award_amount", precision: 7, scale: 2 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["academic_year", "ukprn"], name: "index_eligible_fe_providers_on_academic_year_and_ukprn" + end + create_table "file_uploads", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "uploaded_by_id" t.text "body" diff --git a/db/seeds.rb b/db/seeds.rb index ad90eac8c1..09580403c4 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -17,6 +17,10 @@ Rake::Task["db:fixtures:load"].invoke end +if ENV["ENVIRONMENT_NAME"].start_with?("review") + SchoolDataImporterJob.perform_later if School.count < 100 +end + if Rails.env.development? require "./lib/factory_helpers" diff --git a/docs/connecting-to-azure.md b/docs/connecting-to-azure.md index 587db9ce93..b104dc4371 100644 --- a/docs/connecting-to-azure.md +++ b/docs/connecting-to-azure.md @@ -7,12 +7,6 @@ Kubernetes infrastructure in Azure. Follow these instructions to [run a Rake task](#run-a-rake-task) or [open a Rails console](#open-a-rails-console). -> [!NOTE] These instructions are for connecting to the `test` Kubernetes cluster -> which powers our **Test and PR review environments**. -> -> We don't have a production environment yet – but when we do, we will update -> these instructions accordingly. - ## 1. Authenticate to the Kubernetes cluster You'll need to configure your command line console so it can connect to the @@ -49,19 +43,21 @@ but you may need to re-authenticate every once in a while. brew install Azure/kubelogin/kubelogin ``` -4. Then run: +4. Then run one of these commands: ```shell - make test-aks get-cluster-credentials + make test-aks get-cluster-credentials # for test and review apps + make production-aks get-cluster-credentials CONFIRM_PRODUCTION=yes # for production ``` 5. Assuming everything worked correctly, you should now be able to access the Kubernetes cluster using the `kubectl` command. - > You can test you have access by running this command: + > You can test you have access by running one of these commands: > > ```shell - > kubectl -n srtl-development get deployments + > kubectl -n srtl-test get deployments # for test and review apps + > kubectl -n srtl-production get deployments # for production > ``` > > You should see a list of Kubernetes deployments. @@ -107,25 +103,55 @@ For a list of all test deployments, run: kubectl -n srtl-test get deployments ``` +### Production app + +Our production app is under the `srtl-production` namespace within the +`production` cluster. + +For a list of all test deployments, run: + +```shell +kubectl -n srtl-production get deployments +``` + +> Accessing production deployments requires a +> [PIM (Privileged Identity Management) request](docs/privileged-identity-management-requests.md). + ## 3. Connect to a running container -The following commands will connect to a review app. To connect to the test app, -replace `srtl-development` with `srtl-test` then target the test deployment. +To run the following commands, replace `NAMESPACE` with one of: + +```shell +srtl-production # for production +srtl-test # for test +srtl-development # for review apps +``` + +Replace `DEPLOYMENT_NAME` with the deployment you want to target e.g. +`claim-additional-payments-for-teaching-test-worker`. ### Open a Rails console Open an interactive Rails console using this command: ```shell -kubectl -n srtl-development exec -it deployment/claim-additional-payments-for-teaching-review-123-worker -- rails console +kubectl -n ${NAMESPACE} exec -it deployment/${DEPLOYMENT_NAME} -- rails console ``` +Alternatively, you can run the following script: + +```shell +bin/azure-console ${ENVIRONMENT} +``` + +Where environment is one of `production`, `test` or `review-PR_NUMBER`. + ### Open a shell console Open an interactive Linux shell using this command: ```shell -kubectl -n srtl-development exec -it deployment/claim-additional-payments-for-teaching-review-123-worker -- sh +kubectl -n ${NAMESPACE} exec -it deployment/${DEPLOYMENT_NAME} -- sh ``` ### Run a Rake task @@ -133,13 +159,13 @@ kubectl -n srtl-development exec -it deployment/claim-additional-payments-for-te Run Rake tasks using this command: ```shell -kubectl -n srtl-development exec -it deployment/claim-additional-payments-for-teaching-review-123-worker -- rake [TASK_TO_RUN] +kubectl -n ${NAMESPACE} exec -it deployment/${DEPLOYMENT_NAME} -- rake ${TASK_TO_RUN} ``` Or list all available Rake tasks with: ```shell -kubectl -n srtl-development exec -it deployment/claim-additional-payments-for-teaching-review-123-worker -- rake -T +kubectl -n ${NAMESPACE} exec -it deployment/${DEPLOYMENT_NAME} -- rake -T ``` ## Useful links diff --git a/docs/first-line-support-developer-runbook.md b/docs/first-line-support-developer-runbook.md index 8c53021d31..f240cab053 100644 --- a/docs/first-line-support-developer-runbook.md +++ b/docs/first-line-support-developer-runbook.md @@ -20,13 +20,13 @@ If you want to do one of these tasks and you don’t have what you need, see the 1. Log in to https://portal.azure.com with your `@digital.education.gov.uk` email address. - 2. Search for `s118-teacherpaymentsservice-production`. + 2. Search for `s189-teacher-services-cloud-production`. 3. Click “My permissions”. 4. If you see something like - > You are a member of the group 's118-teacherpaymentservice-Delivery Team - > USR (null)' which has been assigned the role 'Reader' (type BuiltInRole) - > and has access to subscription s118-teacherpaymentsservice-production + > You are a member of the group 's189 SRTL delivery team ()' which has been + > assigned the role 'Reader' (type BuiltInRole) and has access to + > s189-teacher-services-cloud-production then you have what you need. @@ -45,11 +45,10 @@ If you want to do one of these tasks and you don’t have what you need, see the 2. Fix the bug. 3. Describe the fix in [`CHANGELOG.md`](../CHANGELOG.md). -4. Open a pull request into `master`, and get it reviewed. -5. Merge the pull request. -6. If possible, verify that the fix works on the - [development environment](../README.md#development). -7. Do a release. See [`release-process.md`](release-process.md). +4. Open a pull request into `master`. +5. Deploy a review app by adding the 'Deploy' tag to your PR and get it + reviewed. +6. Merge the pull request. ### I want to pull some data from the production database @@ -97,13 +96,13 @@ there is a claim window open, which is around September – March. 1. Log in to https://portal.azure.com with your `@digital.education.gov.uk` email address. - 2. Search for `s118-teacherpaymentsservice-production`. + 2. Search for `s189-teacher-services-cloud-production`. 3. Click “My permissions”. 4. If you see something like - > You are a member of the group 's118-teacherpaymentservice-Delivery Team - > USR (null)' which has been assigned the role 'Reader' (type BuiltInRole) - > and has access to subscription s118-teacherpaymentsservice-production` + > You are a member of the group 's189 SRTL delivery team ()' which has been + > assigned the role 'Reader' (type BuiltInRole) and has access to + > s189-teacher-services-cloud-production then you have what you need. @@ -130,6 +129,7 @@ who raised the support ticket. 4. Identify the latest `PayrollRun` object (double check that the dates are as expected), set `downloaded_at` and `downloaded_by_id` to `nil` and save the object: + ```ruby payroll = PayrollRun.last payroll.downloaded_at = nil @@ -149,8 +149,17 @@ who raised the support ticket. permissions required to access production resources. See [`privileged-identity-management-requests.md`](privileged-identity-management-requests.md). 2. Ask another developer to approve the PIM request. -3. Search for `s118p01-app-worker-aci` within the Azure portal. -4. Click "Restart" -Alternatively, instead of doing it via the web interface, you can run -`az container restart --name s118p01-app-worker-aci --resource-group s118p01-app`. +Then run: + +```bash +kubectl -n srtl-production rollout restart deployment claim-additional-payments-for-teaching-production-worker +``` + +If you need more detailed information about the rollout status, you can describe +the deployment: + +```bash +kubectl -n srtl-test describe deployment +claim-additional-payments-for-teaching-production-worker +``` diff --git a/docs/logging.md b/docs/logging.md index e3c5b58331..dc4d8ceee9 100644 --- a/docs/logging.md +++ b/docs/logging.md @@ -1,33 +1,24 @@ # Logging -# Application-level logging in logit.io +The application logs to STDOUT in JSON format using [Semantic Logger](https://github.com/reidmorrison/rails_semantic_logger). -The application sends all Rails logs to [logit.io](https://logit.io/). This -gives us a hosted ELK stack. ELK stands for Elasticsearch, Logstash, Kibana. -It’s a open-source stack frequently used for log aggregation and visualisation. +# AKS/container logs -Kibana is the tool that you’ll use to explore the logs. +Logs are available via the standard Azure/AKS tooling. -To view the production logs in Kibana: - -1. Log in to logit.io. -2. Click on the “DfE Claim” account. -3. Find the “Production” stack and click “Launch Kibana”. - -## Missing logs in logit.io +The `az` Azure command line tool and `kubectl` have some useful commands for interacting with +logs. -At the time of writing (2020-03-26), we have a problem where some log messages -seem to be missing from logit.io. We are trying to fix this in -[this Trello card](https://trello.com/c/JN44De4l/1330-understand-why-expected-logs-arent-in-logit). +```sh +kubectl -n srtl-test get pods +kubectl -n srtl-test logs claim-additional-payments-for-teaching-test-web-123456 +``` -# Azure logs +You will need PIM elevated privileges to view logs for production. -We should aim for logit.io to be the single place developers need to look to -find logs. However, it’s useful to know about some of the logs that are -available from Azure. +# Logit.io -The `az` Azure command line tool has some useful commands for interacting with -logs. +Logs are shipped to [Logit.io](https://logit.io/) automatically by AKS. You will need an account to access this service. ## App Service @@ -38,27 +29,6 @@ There is some about the logs available for an App Service. Here we go over some of the ways to extract these logs. -### Docker logs - -To view Docker logs in production, you will need to elevate your privileges -using a [PIM request](privileged-identity-management-requests.md). - -You can use the `az webapp log` commands to tail and download the logs. - -Here’s an example command that will live tail the container logs and Docker host -logs, for `production`: - -``` -az webapp log tail --name s118p01-app-as --resource-group s118p01-app --subscription s118-teacherpaymentsservice-production -``` - -Or, you can download them with a browser: - -- production Docker logs from the instances currently in the App Service: - https://s118p01-app-as.scm.azurewebsites.net/api/logs/docker -- production Docker logs from current and previous instances: - https://s118d01-app-as.scm.azurewebsites.net/api/vfs/LogFiles/ - ### Application Insights The Rails application uses the `application_insights` gem, which sends @@ -72,22 +42,3 @@ To view these logs: 3. Click “Logs” under “Monitoring” on the left. 4. You can now execute queries. For example, to view all requests, type `requests` in the query field, and click Run. - -## Container Instances - -The container instances perform other tasks like running a background job -worker. The logs are lost after a deploy. You don’t need PIM-elevated privileges -to view the container instance logs. - -To view the logs for a container instance, we can use `az container logs`: - -``` -az container logs --name s118p01-app-worker-aci --resource-group s118p01-app --subscription s118-teacherpaymentsservice-production -``` - -Or, you can view them in a browser: - -1. Visit `https://portal.azure.com`. -2. Search for `s118p01-app-worker-aci`. -3. Click “Containers” on the left. -4. Click “Logs”. diff --git a/docs/school-check-data.md b/docs/school-check-data.md index 5517e23d42..d6bca1b552 100644 --- a/docs/school-check-data.md +++ b/docs/school-check-data.md @@ -20,47 +20,41 @@ which need this email sending is a developer task, documented below. 3. Have a second developer join you to observe, and connect to the production console using - ``` + ```shell bin/azure-console production ``` -4. Activate the Rails console in sandbox mode with - - ``` - bin/rails console --sandbox - ``` +4. Create a new instance of `Claim::SchoolCheckEmailDataExport` with -5. Create a new instance of `Claim::SchoolCheckEmailDataExport` with - - ``` + ```shell exporter = Claim::SchoolCheckEmailDataExport.new("A1B2C345,D6E7F890,G1H2I345...") ``` substituting the claim references for the string you copied from the spreadsheet in step 2. -6. Generate the CSV data of claims needing checking by running +5. Generate the CSV data of claims needing checking by running - ``` + ```shell puts exporter.csv_string ``` You may need to press the space bar to make your terminal render to the end of the output. -7. Copy the output and save as a CSV file with the name +6. Copy the output and save as a CSV file with the name `school-check-batch_ddmmyyyy.csv` -8. Securely transfer the file to the relevant service operator to follow the +7. Securely transfer the file to the relevant service operator to follow the rest of the school check process. The best way we’ve found to do this is to create a [new Google Sheets document](https://sheets.new/), private to yourself and shared only with the service operator. -9. From the CSV file, copy the claim references (and no other details) and +8. From the CSV file, copy the claim references (and no other details) and append them to the first worksheet in the [School Check Email - Sent Claims spreadsheet](https://docs.google.com/spreadsheets/d/1mxMND-SqOjK7yyYp0EaEJOOCUYFkqLJ1ZIwPLuSVKfM/edit#gid=1926551388) so that they will be excluded the next time the process is run. Trim any remaining empty cells from the bottom of the column -10. After the service operator has sent the school check emails, delete the - personal data from your machine and Google Sheets. +9. After the service operator has sent the school check emails, delete the + personal data from your machine and Google Sheets. diff --git a/filebeat.yml b/filebeat.yml deleted file mode 100644 index 376aaaef85..0000000000 --- a/filebeat.yml +++ /dev/null @@ -1,104 +0,0 @@ -###################### Filebeat Configuration ######################### - -#=========================== Filebeat inputs ============================= - -filebeat.inputs: - -# Each - is an input. Most options can be set at the input level, so -# you can use different inputs for various configurations. -# Below are the input specific configurations. - -- type: log - enabled: true - paths: - - /app/log/*.json - encoding: utf-8 - ignore_older: 3h - json.keys_under_root: true - json.add_error_key: true - - -#============================= Filebeat modules =============================== - -filebeat.config.modules: - # Glob pattern for configuration loading - # path: ${path.config}/modules.d/*.yml - - # Set to true to enable config reloading - # reload.enabled: true - - # Period on which files under path should be checked for changes - # reload.period: 10s - #filebeat.modules: - # - module: system - - -#================================ General ===================================== - -# The name of the shipper that publishes the network data. It can be used to group -# all the transactions sent by a single shipper in the web interface. -#name: - -# The tags of the shipper are included in their own field with each -# transaction published. -#tags: ["service-X", "web-tier"] - -# Optional fields that you can specify to add additional information to the -# output. -fields: - env: "${ENVIRONMENT_NAME}" - -#================================ Outputs ===================================== - -# Configure what output to use when sending the data collected by the beat. - -#----------------------------- Logstash output -------------------------------- -output.logstash: - # The Logstash hosts - hosts: ["${LOGSTASH_HOST}:${LOGSTASH_PORT}"] - loadbalance: true - ssl.enabled: true - - # Optional SSL. By default is off. - # List of root certificates for HTTPS server verifications - #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] - - # Certificate for SSL client authentication - #ssl.certificate: "/etc/pki/client/cert.pem" - - # Client Certificate Key - #ssl.key: "/etc/pki/client/cert.key" - -#================================ Processors ===================================== - -# Configure processors to enhance or manipulate events generated by the beat. - -#processors: -# - add_host_metadata: ~ -# - add_cloud_metadata: ~ - -#================================ Logging ===================================== - -# Sets log level. The default log level is info. -# Available log levels are: error, warning, info, debug -#logging.level: debug - -# At debug level, you can selectively enable logging only for some components. -# To enable all selectors use ["*"]. Examples of other selectors are "beat", -# "publish", "service". -#logging.selectors: ["*"] - -#============================== Xpack Monitoring =============================== -# filebeat can export internal metrics to a central Elasticsearch monitoring -# cluster. This requires xpack monitoring to be enabled in Elasticsearch. The -# reporting is disabled by default. - -# Set to true to enable the monitoring reporter. -#xpack.monitoring.enabled: false - -# Uncomment to send the metrics to Elasticsearch. Most settings from the -# Elasticsearch output are accepted here as well. Any setting that is not set is -# automatically inherited from the Elasticsearch output configuration, so if you -# have the Elasticsearch output configured, you can simply uncomment the -# following line. -#xpack.monitoring.elasticsearch: diff --git a/lib/csv_importer/base.rb b/lib/csv_importer/base.rb index a891b6260d..dd0b593675 100644 --- a/lib/csv_importer/base.rb +++ b/lib/csv_importer/base.rb @@ -4,17 +4,18 @@ module CsvImporter class Base include CsvImporter::Config - attr_reader :errors, :rows + attr_reader :errors, :rows, :deleted_row_count def initialize(file) @errors = [] @rows = parse_csv_file(file) + @deleted_row_count = 0 check_headers if rows && with_headers? end def run - target_data_model.delete_all unless append_only + @deleted_row_count = delete_all_scope.delete_all unless append_only rows.each_slice(batch_size).with_index(1) do |batch_rows, i| Rails.logger.info "Processing #{target_data_model.to_s.titleize} batch #{i}" @@ -31,6 +32,10 @@ def run private + def delete_all_scope + target_data_model + end + def with_headers? parse_headers && mandatory_headers&.is_a?(Array) && mandatory_headers&.any? end diff --git a/package.json b/package.json index cfc18dfd8d..b404d76223 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,6 @@ "govuk-frontend": "^5.4.0" }, "devDependencies": { - "prettier": "^3.3.2" + "prettier": "^3.3.3" } } diff --git a/spec/factories/eligible_fe_providers.rb b/spec/factories/eligible_fe_providers.rb new file mode 100644 index 0000000000..32269cff59 --- /dev/null +++ b/spec/factories/eligible_fe_providers.rb @@ -0,0 +1,8 @@ +FactoryBot.define do + factory :eligible_fe_provider do + ukprn { rand(10_000_000..19_000_000) } + academic_year { AcademicYear.current } + max_award_amount { [4_000, 5_000, 6_000].sample } + lower_award_amount { [2_000, 2_500, 3_000].sample } + end +end diff --git a/spec/factories/journeys/get_a_teacher_relocation_payment/get_a_teacher_relocation_payment_answers.rb b/spec/factories/journeys/get_a_teacher_relocation_payment/get_a_teacher_relocation_payment_answers.rb index a52b2c0e0a..38411a027a 100644 --- a/spec/factories/journeys/get_a_teacher_relocation_payment/get_a_teacher_relocation_payment_answers.rb +++ b/spec/factories/journeys/get_a_teacher_relocation_payment/get_a_teacher_relocation_payment_answers.rb @@ -70,7 +70,7 @@ bank_account_number { rand(10000000..99999999) } end - trait :with_employment_details do + trait :with_headteacher_details do school_headteacher_name { "Seymour Skinner" } end @@ -78,6 +78,7 @@ with_teacher_application_route with_state_funded_secondary_school with_current_school + with_headteacher_details with_one_year_contract with_subject with_start_date diff --git a/spec/factories/policies/international_relocation_payments/eligibilities.rb b/spec/factories/policies/international_relocation_payments/eligibilities.rb index d1ba1ef6f4..01adc6b455 100644 --- a/spec/factories/policies/international_relocation_payments/eligibilities.rb +++ b/spec/factories/policies/international_relocation_payments/eligibilities.rb @@ -1,7 +1,9 @@ FactoryBot.define do factory :international_relocation_payments_eligibility, class: "Policies::InternationalRelocationPayments::Eligibility" do + award_amount { Policies::InternationalRelocationPayments.award_amount } + trait :eligible_home_office do - passport_number { "123456789" } + passport_number { Faker::Number.unique.number(digits: 9).to_s } nationality { "French" } end @@ -11,6 +13,7 @@ eligible_home_office eligible_school eligible_subject + eligible_start_date end trait :eligible_school do diff --git a/spec/features/admin/eligible_fe_providers_spec.rb b/spec/features/admin/eligible_fe_providers_spec.rb new file mode 100644 index 0000000000..c3b16789c3 --- /dev/null +++ b/spec/features/admin/eligible_fe_providers_spec.rb @@ -0,0 +1,40 @@ +require "rails_helper" + +RSpec.feature "Admin of eligible FE providers" do + scenario "manage eligible FE providers" do + when_further_education_payments_journey_configuration_exists + sign_in_as_service_operator + + click_link "Manage services" + click_link "Change Claim incentive payments for further education teachers" + + select "2024/2025", from: "eligible-fe-providers-upload-academic-year-field" + attach_file "eligible-fe-providers-upload-file-field", eligible_fe_providers_csv_file.path + click_button "Upload CSV" + + expect(page).to have_select "eligible-fe-providers-upload-academic-year-field", selected: "2024/2025" + + select "2024/2025", from: "eligible-fe-providers-download-academic-year-field" + click_button "Download CSV" + + downloaded_csv = page.body + + expect(downloaded_csv).to eql(eligible_fe_providers_csv_file.read) + end + + def eligible_fe_providers_csv_file + return @eligible_fe_providers_csv_file if @eligible_fe_providers_csv_file + + @eligible_fe_providers_csv_file = Tempfile.new + @eligible_fe_providers_csv_file.write EligibleFeProvidersImporter.mandatory_headers.join(",") + "\n" + + 3.times do + hash = attributes_for(:eligible_fe_provider) + @eligible_fe_providers_csv_file.write "#{hash[:ukprn]},#{hash[:max_award_amount].to_f},#{hash[:lower_award_amount].to_f}\n" + end + + @eligible_fe_providers_csv_file.rewind + + @eligible_fe_providers_csv_file + end +end diff --git a/spec/features/further_education_payments/college_not_found_spec.rb b/spec/features/further_education_payments/college_not_found_spec.rb index 89075664c2..51deb47bcc 100644 --- a/spec/features/further_education_payments/college_not_found_spec.rb +++ b/spec/features/further_education_payments/college_not_found_spec.rb @@ -38,8 +38,4 @@ expect(page).to have_content("Which FE provider are you employed by?") expect(page).to have_content("No results match that search term. Try again.") end - - def when_further_education_payments_journey_configuration_exists - create(:journey_configuration, :further_education_payments) - end end diff --git a/spec/features/further_education_payments/happy_js_path_spec.rb b/spec/features/further_education_payments/happy_js_path_spec.rb index 0d6cfda610..917a308c6c 100644 --- a/spec/features/further_education_payments/happy_js_path_spec.rb +++ b/spec/features/further_education_payments/happy_js_path_spec.rb @@ -18,6 +18,7 @@ expect(page).to have_content("Which FE provider are you employed by?") fill_in "Which FE provider are you employed by?", with: college.name within("#claim-provision-search-field__listbox") do + sleep(1) # seems to aid in success, as if click happens before event is bound find("li", text: college.name).click end click_button "Continue" @@ -42,10 +43,13 @@ check("Building and construction") click_button "Continue" - expect(page).to have_content("FE building and construction courses goes here") + expect(page).to have_content("Which building and construction courses do you teach?") + check "T Level in building services engineering for construction" click_button "Continue" - expect(page).to have_content("FE teaching courses goes here") + expect(page).to have_content("Do you spend at least half of your timetabled teaching hours teaching these eligible courses?") + expect(page).to have_content("T Level in building services engineering for construction") + choose("Yes") click_button "Continue" expect(page).to have_content("Are at least half of your timetabled teaching hours spent teaching 16 to 19-year-olds, including those up to age 25 with an Education, Health and Care Plan (EHCP)?") @@ -69,15 +73,72 @@ expect(page).to have_content("Check your answers") click_button "Continue" - expect(page).to have_content("FE check your answers goes here") - click_button "Continue" - expect(page).to have_content("You’re eligible for a financial incentive payment") expect(page).to have_content("Apply now") - end + click_button "Apply now" + + expect(page).to have_content("FE ONE LOGIN PLACEHOLDER") + click_button "Continue" + + expect(page).to have_content("How we will use the information you provide in your application") + click_button "Continue" - def when_further_education_payments_journey_configuration_exists - create(:journey_configuration, :further_education_payments) + expect(page).to have_content("Personal details") + fill_in "First name", with: "John" + fill_in "Last name", with: "Doe" + fill_in "Day", with: "28" + fill_in "Month", with: "2" + fill_in "Year", with: "1988" + fill_in "National Insurance number", with: "PX321499A" + click_on "Continue" + + expect(page).to have_content("What is your home address?") + click_link("Enter your address manually") + + expect(page).to have_content("What is your address?") + fill_in "House number or name", with: "57" + fill_in "Building and street", with: "Walthamstow Drive" + fill_in "Town or city", with: "Derby" + fill_in "County", with: "City of Derby" + fill_in "Postcode", with: "DE22 4BS" + click_on "Continue" + + expect(page).to have_content("Email address") + fill_in "Email address", with: "johndoe@example.com" + click_on "Continue" + + expect(page).to have_content("Enter the 6-digit passcode") + mail = ActionMailer::Base.deliveries.last + otp_in_mail_sent = mail[:personalisation].decoded.scan(/\b[0-9]{6}\b/).first + fill_in "claim-one-time-password-field", with: otp_in_mail_sent + click_on "Confirm" + + expect(page).to have_content("Would you like to provide your mobile number?") + choose "No" + click_on "Continue" + + expect(page).to have_content("What account do you want the money paid into?") + choose "Personal bank account" + click_on "Continue" + + expect(page).to have_content("Enter your personal bank account details") + fill_in "Name on your account", with: "Jo Bloggs" + fill_in "Sort code", with: "123456" + fill_in "Account number", with: "87654321" + click_on "Continue" + + expect(page).to have_content("How is your gender recorded on your employer’s payroll system?") + choose "Female" + click_on "Continue" + + expect(page).to have_content("What is your teacher reference number (TRN)?") + fill_in "claim-teacher-reference-number-field", with: "1234567" + click_on "Continue" + + expect(page).to have_content("Check your answers before sending your application") + click_on "Accept and send" + + expect(page).to have_content("You applied for a further education financial incentive payment") end def and_college_exists diff --git a/spec/features/further_education_payments/happy_path_spec.rb b/spec/features/further_education_payments/happy_path_spec.rb index 559fe01436..a07e28fe5a 100644 --- a/spec/features/further_education_payments/happy_path_spec.rb +++ b/spec/features/further_education_payments/happy_path_spec.rb @@ -24,15 +24,7 @@ click_button "Continue" expect(page).to have_content("What type of contract do you have with #{college.name}?") - choose("Fixed-term contract") - click_button "Continue" - - expect(page).to have_content("Does your fixed-term contract cover the full #{AcademicYear.current.to_s(:long)} academic year?") - choose("No") - click_button "Continue" - - expect(page).to have_content("Have you taught at #{college.name} for at least one academic term?") - choose("Yes, I have taught at #{college.name} for at least one academic term") + choose("Permanent contract") click_button "Continue" expect(page).to have_content("On average, how many hours per week are you timetabled to teach at #{college.name} during the current term?") @@ -45,12 +37,51 @@ expect(page).to have_content("Which subject areas do you teach?") check("Building and construction") + check("Chemistry") + check("Computing, including digital and ICT") + check("Early years") + check("Engineering and manufacturing, including transport engineering and electronics") + check("Maths") + check("Physics") + click_button "Continue" + + expect(page).to have_content("Which building and construction courses do you teach?") + check "T Level in building services engineering for construction" + click_button "Continue" + + expect(page).to have_content("Which chemistry courses do you teach?") + check "GCSE chemistry" + click_button "Continue" + + expect(page).to have_content("Which computing courses do you teach?") + check "T Level in digital support services" + click_button "Continue" + + expect(page).to have_content("Which early years courses do you teach?") + check "T Level in education and early years (early years educator)" + click_button "Continue" + + expect(page).to have_content("Which engineering and manufacturing courses do you teach?") + check "T Level in design and development for engineering and manufacturing" click_button "Continue" - expect(page).to have_content("FE building and construction courses goes here") + expect(page).to have_content("Which maths courses do you teach?") + check("claim-maths-courses-esfa-field") click_button "Continue" - expect(page).to have_content("FE teaching courses goes here") + expect(page).to have_content("Which physics courses do you teach?") + check "A or AS level physics" + click_button "Continue" + + expect(page).to have_content("Do you spend at least half of your timetabled teaching hours teaching these eligible courses?") + expect(page).to have_content("T Level in building services engineering for construction") + expect(page).to have_content("GCSE chemistry") + expect(page).to have_content("T Level in digital support services") + expect(page).to have_content("T Level in education and early years (early years educator)") + expect(page).to have_content("T Level in design and development for engineering and manufacturing") + expect(page).to have_content("ESFA-funded qualifications at level 3 and below in the") + expect(page).to have_content("A or AS level physics") + choose("Yes") click_button "Continue" expect(page).to have_content("Are at least half of your timetabled teaching hours spent teaching 16 to 19-year-olds, including those up to age 25 with an Education, Health and Care Plan (EHCP)?") @@ -74,15 +105,72 @@ expect(page).to have_content("Check your answers") click_button "Continue" - expect(page).to have_content("FE check your answers goes here") - click_button "Continue" - expect(page).to have_content("You’re eligible for a financial incentive payment") expect(page).to have_content("Apply now") - end + click_button "Apply now" + + expect(page).to have_content("FE ONE LOGIN PLACEHOLDER") + click_button "Continue" + + expect(page).to have_content("How we will use the information you provide in your application") + click_button "Continue" + + expect(page).to have_content("Personal details") + fill_in "First name", with: "John" + fill_in "Last name", with: "Doe" + fill_in "Day", with: "28" + fill_in "Month", with: "2" + fill_in "Year", with: "1988" + fill_in "National Insurance number", with: "PX321499A" + click_on "Continue" + + expect(page).to have_content("What is your home address?") + click_link("Enter your address manually") + + expect(page).to have_content("What is your address?") + fill_in "House number or name", with: "57" + fill_in "Building and street", with: "Walthamstow Drive" + fill_in "Town or city", with: "Derby" + fill_in "County", with: "City of Derby" + fill_in "Postcode", with: "DE22 4BS" + click_on "Continue" + + expect(page).to have_content("Email address") + fill_in "Email address", with: "johndoe@example.com" + click_on "Continue" + + expect(page).to have_content("Enter the 6-digit passcode") + mail = ActionMailer::Base.deliveries.last + otp_in_mail_sent = mail[:personalisation].decoded.scan(/\b[0-9]{6}\b/).first + fill_in "claim-one-time-password-field", with: otp_in_mail_sent + click_on "Confirm" + + expect(page).to have_content("Would you like to provide your mobile number?") + choose "No" + click_on "Continue" + + expect(page).to have_content("What account do you want the money paid into?") + choose "Personal bank account" + click_on "Continue" + + expect(page).to have_content("Enter your personal bank account details") + fill_in "Name on your account", with: "Jo Bloggs" + fill_in "Sort code", with: "123456" + fill_in "Account number", with: "87654321" + click_on "Continue" + + expect(page).to have_content("How is your gender recorded on your employer’s payroll system?") + choose "Female" + click_on "Continue" + + expect(page).to have_content("What is your teacher reference number (TRN)?") + fill_in "claim-teacher-reference-number-field", with: "1234567" + click_on "Continue" + + expect(page).to have_content("Check your answers before sending your application") + click_on "Accept and send" - def when_further_education_payments_journey_configuration_exists - create(:journey_configuration, :further_education_payments) + expect(page).to have_content("You applied for a further education financial incentive payment") end def and_college_exists diff --git a/spec/features/further_education_payments/ineligible_paths_spec.rb b/spec/features/further_education_payments/ineligible_paths_spec.rb index 652513e2ef..9e5197ef8c 100644 --- a/spec/features/further_education_payments/ineligible_paths_spec.rb +++ b/spec/features/further_education_payments/ineligible_paths_spec.rb @@ -55,8 +55,49 @@ expect(page).to have_content("You are not eligible for a financial incentive payment yet") end + scenario "when lacking subjects" do + when_further_education_payments_journey_configuration_exists + and_college_exists + + visit landing_page_path(Journeys::FurtherEducationPayments::ROUTING_NAME) + expect(page).to have_link("Start now") + click_link "Start now" + + expect(page).to have_content("Are you a member of staff with teaching responsibilities?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Which FE provider are you employed by?") + fill_in "Which FE provider are you employed by?", with: college.name + click_button "Continue" + + expect(page).to have_content("Select the college you teach at") + choose college.name + click_button "Continue" + + expect(page).to have_content("What type of contract do you have with #{college.name}?") + choose "Permanent contract" + click_button "Continue" + + expect(page).to have_content("On average, how many hours per week") + choose "More than 12 hours per week" + click_button "Continue" + + expect(page).to have_content("Which academic year did you start teaching in further education (FE) in England?") + choose "September 2023 to August 2024" + click_button "Continue" + + expect(page).to have_content("Which subject areas do you teach?") + check "I do not teach any of these subjects" + click_button "Continue" + + expect(page).to have_content("You are not eligible") + expect(page).to have_content("you must teach an eligible FE subject") + end + scenario "when variable contract and just one academic term taught" do when_further_education_payments_journey_configuration_exists + and_college_exists visit landing_page_path(Journeys::FurtherEducationPayments::ROUTING_NAME) expect(page).to have_link("Start now") @@ -85,8 +126,427 @@ expect(page).to have_content("You are not eligible for a financial incentive payment yet") end - def when_further_education_payments_journey_configuration_exists - create(:journey_configuration, :further_education_payments) + scenario "when teaches non eligible course in applicable subject area" do + when_further_education_payments_journey_configuration_exists + and_college_exists + + visit landing_page_path(Journeys::FurtherEducationPayments::ROUTING_NAME) + expect(page).to have_link("Start now") + click_link "Start now" + + expect(page).to have_content("Are you a member of staff with teaching responsibilities?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Which FE provider are you employed by?") + fill_in "Which FE provider are you employed by?", with: college.name + click_button "Continue" + + expect(page).to have_content("Select the college you teach at") + choose college.name + click_button "Continue" + + expect(page).to have_content("What type of contract do you have with #{college.name}?") + choose "Permanent contract" + click_button "Continue" + + expect(page).to have_content("On average, how many hours per week") + choose "More than 12 hours per week" + click_button "Continue" + + expect(page).to have_content("Which academic year did you start teaching in further education (FE) in England?") + choose "September 2023 to August 2024" + click_button "Continue" + + expect(page).to have_content("Which subject areas do you teach?") + check "Building and construction" + click_button "Continue" + + expect(page).to have_content("Which building and construction courses do you teach?") + check "I do not teach any of these courses" + click_button "Continue" + + expect(page).to have_content("You are not eligible") + expect(page).to have_content("you must teach an eligible FE course") + end + + scenario "when not a recent FE teacher" do + when_further_education_payments_journey_configuration_exists + + visit landing_page_path(Journeys::FurtherEducationPayments::ROUTING_NAME) + expect(page).to have_link("Start now") + click_link "Start now" + + expect(page).to have_content("Are you a member of staff with teaching responsibilities?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Which FE provider are you employed by?") + fill_in "Which FE provider are you employed by?", with: college.name + click_button "Continue" + + expect(page).to have_content("Select the college you teach at") + choose college.name + click_button "Continue" + + expect(page).to have_content("What type of contract do you have with #{college.name}?") + choose("Permanent contract") + click_button "Continue" + + expect(page).to have_content("On average, how many hours per week are you timetabled to teach at #{college.name} during the current term?") + choose("More than 12 hours per week") + click_button "Continue" + + expect(page).to have_content("Which academic year did you start teaching in further education (FE) in England?") + choose("I started before September #{current_academic_year.start_year - 4}") + click_button "Continue" + + expect(page).to have_content("You are not eligible") + expect(page).to have_content("you must be in the first 5 years of") + end + + scenario "when teacher is subject to performance measures" do + when_further_education_payments_journey_configuration_exists + + visit landing_page_path(Journeys::FurtherEducationPayments::ROUTING_NAME) + expect(page).to have_link("Start now") + click_link "Start now" + + expect(page).to have_content("Are you a member of staff with teaching responsibilities?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Which FE provider are you employed by?") + fill_in "Which FE provider are you employed by?", with: college.name + click_button "Continue" + + expect(page).to have_content("Select the college you teach at") + choose college.name + click_button "Continue" + + expect(page).to have_content("What type of contract do you have with #{college.name}?") + choose "Permanent contract" + click_button "Continue" + expect(page).to have_content("On average, how many hours per week are you timetabled to teach at #{college.name} during the current term?") + choose "More than 12 hours per week" + click_button "Continue" + + expect(page).to have_content("Which academic year did you start teaching in further education (FE) in England?") + choose "September 2023 to August 2024" + click_button "Continue" + + expect(page).to have_content("Which subject areas do you teach?") + check "Building and construction" + click_button "Continue" + + expect(page).to have_content("Which building and construction courses do you teach?") + check "T Level in onsite construction" + click_button "Continue" + + expect(page).to have_content("Do you spend at least half of your timetabled teaching hours teaching these eligible courses?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Are at least half of your timetabled teaching hours spent teaching 16 to 19-year-olds, including those up to age 25 with an Education, Health and Care Plan (EHCP)?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Do you have a teaching qualification?") + choose("Yes") + click_button "Continue" + + expect(page).to have_content("Have any performance measures been started against you?") + within all(".govuk-fieldset")[0] do + choose("Yes") + end + expect(page).to have_content("Are you currently subject to disciplinary action?") + within all(".govuk-fieldset")[1] do + choose("No") + end + click_button "Continue" + + expect(page).to have_content("You are not eligible") + expect(page).to have_content("you must not currently be subject to any") + end + + scenario "when teacher is subject to disciplinary action" do + when_further_education_payments_journey_configuration_exists + + visit landing_page_path(Journeys::FurtherEducationPayments::ROUTING_NAME) + expect(page).to have_link("Start now") + click_link "Start now" + + expect(page).to have_content("Are you a member of staff with teaching responsibilities?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Which FE provider are you employed by?") + fill_in "Which FE provider are you employed by?", with: college.name + click_button "Continue" + + expect(page).to have_content("Select the college you teach at") + choose college.name + click_button "Continue" + + expect(page).to have_content("What type of contract do you have with #{college.name}?") + choose "Permanent contract" + click_button "Continue" + + expect(page).to have_content("On average, how many hours per week are you timetabled to teach at #{college.name} during the current term?") + choose "More than 12 hours per week" + click_button "Continue" + + expect(page).to have_content("Which academic year did you start teaching in further education (FE) in England?") + choose "September 2023 to August 2024" + click_button "Continue" + + expect(page).to have_content("Which subject areas do you teach?") + check "Building and construction" + click_button "Continue" + + expect(page).to have_content("Which building and construction courses do you teach?") + check "T Level in onsite construction" + click_button "Continue" + + expect(page).to have_content("Do you spend at least half of your timetabled teaching hours teaching these eligible courses?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Are at least half of your timetabled teaching hours spent teaching 16 to 19-year-olds, including those up to age 25 with an Education, Health and Care Plan (EHCP)?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Do you have a teaching qualification?") + choose("Yes") + click_button "Continue" + + expect(page).to have_content("Have any performance measures been started against you?") + within all(".govuk-fieldset")[0] do + choose("No") + end + expect(page).to have_content("Are you currently subject to disciplinary action?") + within all(".govuk-fieldset")[1] do + choose("Yes") + end + click_button "Continue" + + expect(page).to have_content("You are not eligible") + expect(page).to have_content("you must not currently be subject to any") + end + + scenario "when lacks teaching qualification and no enrol plan" do + when_further_education_payments_journey_configuration_exists + + visit landing_page_path(Journeys::FurtherEducationPayments::ROUTING_NAME) + expect(page).to have_link("Start now") + click_link "Start now" + + expect(page).to have_content("Are you a member of staff with teaching responsibilities?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Which FE provider are you employed by?") + fill_in "Which FE provider are you employed by?", with: college.name + click_button "Continue" + + expect(page).to have_content("Select the college you teach at") + choose college.name + click_button "Continue" + + expect(page).to have_content("What type of contract do you have with #{college.name}?") + choose "Permanent contract" + click_button "Continue" + + expect(page).to have_content("On average, how many hours per week are you timetabled to teach at #{college.name} during the current term?") + choose "More than 12 hours per week" + click_button "Continue" + + expect(page).to have_content("Which academic year did you start teaching in further education (FE) in England?") + choose "September 2023 to August 2024" + click_button "Continue" + + expect(page).to have_content("Which subject areas do you teach?") + check "Building and construction" + click_button "Continue" + + expect(page).to have_content("Which building and construction courses do you teach?") + check "T Level in onsite construction" + click_button "Continue" + + expect(page).to have_content("Do you spend at least half of your timetabled teaching hours teaching these eligible courses?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Are at least half of your timetabled teaching hours spent teaching 16 to 19-year-olds, including those up to age 25 with an Education, Health and Care Plan (EHCP)?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Do you have a teaching qualification?") + choose "No, and I do not plan to enrol on one in the next 12 months" + click_button "Continue" + + expect(page).to have_content("You are not eligible") + expect(page).to have_content("plan to enrol on a teaching qualification in the next 12 months") + end + + scenario "when permanent contract and not enough hours" do + when_further_education_payments_journey_configuration_exists + + visit landing_page_path(Journeys::FurtherEducationPayments::ROUTING_NAME) + expect(page).to have_link("Start now") + click_link "Start now" + + expect(page).to have_content("Are you a member of staff with teaching responsibilities?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Which FE provider are you employed by?") + fill_in "Which FE provider are you employed by?", with: college.name + click_button "Continue" + + expect(page).to have_content("Select the college you teach at") + choose college.name + click_button "Continue" + + expect(page).to have_content("What type of contract do you have with #{college.name}?") + choose "Permanent contract" + click_button "Continue" + + expect(page).to have_content("On average, how many hours per week are you timetabled to teach at #{college.name} during the current term?") + choose("Less than 2.5 hours per week") + click_button "Continue" + + expect(page).to have_content("You are not eligible") + expect(page).to have_content("teach at least 2.5 hours per week") + end + + scenario "when fixed-term contract and not enough hours" do + when_further_education_payments_journey_configuration_exists + + visit landing_page_path(Journeys::FurtherEducationPayments::ROUTING_NAME) + expect(page).to have_link("Start now") + click_link "Start now" + + expect(page).to have_content("Are you a member of staff with teaching responsibilities?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Which FE provider are you employed by?") + fill_in "Which FE provider are you employed by?", with: college.name + click_button "Continue" + + expect(page).to have_content("Select the college you teach at") + choose college.name + click_button "Continue" + + expect(page).to have_content("What type of contract do you have with #{college.name}?") + choose "Fixed-term contract" + click_button "Continue" + + expect(page).to have_content("Does your fixed-term contract cover the full #{current_academic_year.to_s(:long)} academic year?") + choose "Yes, it covers the full #{current_academic_year.to_s(:long)} academic year" + click_button "Continue" + + expect(page).to have_content("On average, how many hours per week are you timetabled to teach at #{college.name} during the current term?") + choose "More than 12 hours per week" + click_button "Continue" + + expect(page).to have_content("Are you timetabled to teach at least 2.5 hours per week at #{college.name} next term?") + choose("No, I’m not timetabled to teach at least 2.5 hours per week at #{college.name} next term") + click_button "Continue" + + expect(page).to have_content("You are not eligible") + expect(page).to have_content("teach at least 2.5 hours per week") + end + + scenario "when variable contract and not enough hours" do + when_further_education_payments_journey_configuration_exists + + visit landing_page_path(Journeys::FurtherEducationPayments::ROUTING_NAME) + expect(page).to have_link("Start now") + click_link "Start now" + + expect(page).to have_content("Are you a member of staff with teaching responsibilities?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Which FE provider are you employed by?") + fill_in "Which FE provider are you employed by?", with: college.name + click_button "Continue" + + expect(page).to have_content("Select the college you teach at") + choose college.name + click_button "Continue" + + expect(page).to have_content("What type of contract do you have with #{college.name}?") + choose("Variable hours contract") + click_button "Continue" + + expect(page).to have_content("Have you taught at #{college.name} for at least one academic term?") + choose("Yes, I have taught at #{college.name} for at least one academic term") + click_button "Continue" + + expect(page).to have_content("On average, how many hours per week are you timetabled to teach at #{college.name} during the current term?") + choose("More than 12 hours per week") + click_button "Continue" + + expect(page).to have_content("Are you timetabled to teach at least 2.5 hours per week at #{college.name} next term?") + choose("No, I’m not timetabled to teach at least 2.5 hours per week at #{college.name} next term") + click_button "Continue" + + expect(page).to have_content("You are not eligible") + expect(page).to have_content("teach at least 2.5 hours per week") + end + + scenario "when less that 50% teaching hours to FE" do + when_further_education_payments_journey_configuration_exists + + visit landing_page_path(Journeys::FurtherEducationPayments::ROUTING_NAME) + expect(page).to have_link("Start now") + click_link "Start now" + + expect(page).to have_content("Are you a member of staff with teaching responsibilities?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Which FE provider are you employed by?") + fill_in "Which FE provider are you employed by?", with: college.name + click_button "Continue" + + expect(page).to have_content("Select the college you teach at") + choose college.name + click_button "Continue" + + expect(page).to have_content("What type of contract do you have with #{college.name}?") + choose("Permanent contract") + click_button "Continue" + + expect(page).to have_content("On average, how many hours per week are you timetabled to teach at #{college.name} during the current term?") + choose("More than 12 hours per week") + click_button "Continue" + + expect(page).to have_content("Which academic year did you start teaching in further education (FE) in England?") + choose("September 2023 to August 2024") + click_button "Continue" + + expect(page).to have_content("Which subject areas do you teach?") + check "Building and construction" + click_button "Continue" + + expect(page).to have_content("Which building and construction courses do you teach?") + check "T Level in onsite construction" + click_button "Continue" + + expect(page).to have_content("Do you spend at least half of your timetabled teaching hours teaching these eligible courses?") + choose "Yes" + click_button "Continue" + + expect(page).to have_content("Are at least half of your timetabled teaching hours spent teaching 16 to 19-year-olds, including those up to age 25 with an Education, Health and Care Plan (EHCP)?") + choose "No" + click_button "Continue" + + expect(page).to have_content("You are not eligible") + expect(page).to have_content("half of your timetabled teaching hours must include") end def and_college_exists diff --git a/spec/features/get_a_teacher_relocation_payment/ineligible_route_completing_the_form_spec.rb b/spec/features/get_a_teacher_relocation_payment/ineligible_route_completing_the_form_spec.rb index 73944cbeb0..637c37c219 100644 --- a/spec/features/get_a_teacher_relocation_payment/ineligible_route_completing_the_form_spec.rb +++ b/spec/features/get_a_teacher_relocation_payment/ineligible_route_completing_the_form_spec.rb @@ -68,6 +68,7 @@ ) and_i_complete_the_state_funded_secondary_school_step_with(option: "Yes") and_i_complete_the_current_school_step(create(:school, phase: :secondary)) + and_i_complete_the_headteacher_step and_i_complete_the_contract_details_step_with(option: "No") then_i_see_the_ineligible_page end @@ -81,6 +82,7 @@ ) and_i_complete_the_state_funded_secondary_school_step_with(option: "Yes") and_i_complete_the_current_school_step(create(:school, phase: :secondary)) + and_i_complete_the_headteacher_step and_i_complete_the_contract_details_step_with(option: "Yes") and_i_complete_the_contract_start_date_step_with( date: Policies::InternationalRelocationPayments::PolicyEligibilityChecker @@ -98,6 +100,7 @@ ) and_i_complete_the_state_funded_secondary_school_step_with(option: "Yes") and_i_complete_the_current_school_step(create(:school, phase: :secondary)) + and_i_complete_the_headteacher_step and_i_complete_the_contract_details_step_with(option: "Yes") and_i_complete_the_contract_start_date_step_with( date: contract_start_date @@ -115,6 +118,7 @@ ) and_i_complete_the_state_funded_secondary_school_step_with(option: "Yes") and_i_complete_the_current_school_step(create(:school, phase: :secondary)) + and_i_complete_the_headteacher_step and_i_complete_the_contract_details_step_with(option: "Yes") and_i_complete_the_contract_start_date_step_with( date: contract_start_date @@ -133,6 +137,7 @@ ) and_i_complete_the_state_funded_secondary_school_step_with(option: "Yes") and_i_complete_the_current_school_step(create(:school, phase: :secondary)) + and_i_complete_the_headteacher_step and_i_complete_the_contract_details_step_with(option: "Yes") and_i_complete_the_contract_start_date_step_with( date: contract_start_date diff --git a/spec/features/get_a_teacher_relocation_payment/teacher_route_completing_the_form_spec.rb b/spec/features/get_a_teacher_relocation_payment/teacher_route_completing_the_form_spec.rb index c034ea0e6c..89a253c0e0 100644 --- a/spec/features/get_a_teacher_relocation_payment/teacher_route_completing_the_form_spec.rb +++ b/spec/features/get_a_teacher_relocation_payment/teacher_route_completing_the_form_spec.rb @@ -32,6 +32,7 @@ ) and_i_complete_the_state_funded_secondary_school_step_with(option: "Yes") and_i_complete_the_current_school_step(school) + and_i_complete_the_headteacher_step and_i_complete_the_contract_details_step_with(option: "Yes") and_i_complete_the_contract_start_date_step_with( date: contract_start_date @@ -47,7 +48,6 @@ it "submits an application" do and_i_complete_the_nationality_step_with(option: "Australian") and_i_complete_the_passport_number_step_with(options: "123456789") - and_i_complete_the_headteacher_step and_i_complete_the_personal_details_step and_i_complete_the_postcode_step and_i_complete_the_email_address_step @@ -64,7 +64,6 @@ it "submits an application", js: true do and_i_complete_the_nationality_step_with(option: "Australian") and_i_complete_the_passport_number_step_with(options: "123456789") - and_i_complete_the_headteacher_step and_i_complete_the_personal_details_step and_i_complete_the_manual_address_step and_i_complete_the_email_address_step @@ -81,7 +80,6 @@ it "submits an application" do and_i_complete_the_nationality_step_with(option: "Australian") and_i_complete_the_passport_number_step_with(options: "123456789") - and_i_complete_the_headteacher_step and_i_complete_the_personal_details_step and_i_complete_the_manual_address_step and_i_complete_the_email_address_step @@ -98,7 +96,6 @@ it "submits an application" do and_i_complete_the_nationality_step_with(option: "Australian") and_i_complete_the_passport_number_step_with(options: "123456789") - and_i_complete_the_headteacher_step and_i_complete_the_personal_details_step and_i_complete_the_manual_address_step and_i_complete_the_email_address_step @@ -131,6 +128,10 @@ def then_the_check_your_answers_part_one_page_shows_my_answers "Which school are you currently employed to teach at? #{school.name}" ) + expect(page).to have_text( + "Enter the name of the headteacher of the school where you are employed as a teacher Seymour Skinner" + ) + expect(page).to have_text( "Are you employed on a contract lasting at least one year? Yes" ) @@ -179,10 +180,6 @@ def then_the_check_your_answers_part_page_shows_my_answers(school, mobile_number "Enter your passport number, as it appears on your passport 123456789" ) - expect(page).to have_text( - "Enter the name of the headteacher of the school where you are employed as a teacher Seymour Skinner" - ) - if mobile_number expect(page).to have_text("Mobile number 01234567890") else diff --git a/spec/forms/form_spec.rb b/spec/forms/form_spec.rb index c54c9df484..de7e53d8b9 100644 --- a/spec/forms/form_spec.rb +++ b/spec/forms/form_spec.rb @@ -163,6 +163,53 @@ def initialize(journey_session) end end + describe "#t" do + let(:form) { TestSlugForm.new(journey:, journey_session:, params:) } + let(:args) { {} } + let(:key) { "some_key" } + + before do + allow(I18n).to receive(:t) + form.t(key, args) + end + + context "no args" do + it do + expect(I18n).to have_received(:t).with("test_i18n_ns.forms.test_slug.some_key", {default: :"forms.test_slug.some_key"}) + end + end + + context "override i18n_form_namespace" do + let(:args) { {i18n_form_namespace: "overriden_ns"} } + + it do + expect(I18n).to have_received(:t).with("test_i18n_ns.forms.overriden_ns.some_key", {default: :"forms.overriden_ns.some_key"}) + end + end + end + + describe "#t - actually use something from en.yml" do + let(:params) { ActionController::Parameters.new({}) } + + subject(:form) { GenderForm.new(journey:, journey_session:, params:) } + + context "FE journey overrides gender form in en.yml" do + let(:journey) { Journeys::FurtherEducationPayments } + + it "calls the i18n namespaced version" do + expect(form.t("questions.payroll_gender")).to eq("How is your gender recorded on your employer’s payroll system?") + end + end + + context "TSLR journey uses the base gender form in en.yml" do + let(:journey) { Journeys::TeacherStudentLoanReimbursement } + + it "calls the base version" do + expect(form.t("questions.payroll_gender")).to eq("How is your gender recorded on your school’s payroll system?") + end + end + end + describe "#permitted_params" do let(:claim_params) { {first_name: "test-value"} } diff --git a/spec/forms/journeys/further_education_payments/building_construction_courses_form_spec.rb b/spec/forms/journeys/further_education_payments/building_construction_courses_form_spec.rb new file mode 100644 index 0000000000..f1fc475eba --- /dev/null +++ b/spec/forms/journeys/further_education_payments/building_construction_courses_form_spec.rb @@ -0,0 +1,55 @@ +require "rails_helper" + +RSpec.describe Journeys::FurtherEducationPayments::BuildingConstructionCoursesForm, type: :model do + let(:journey) { Journeys::FurtherEducationPayments } + let(:journey_session) { create(:further_education_payments_session) } + let(:building_construction_courses) { [""] } + + let(:params) do + ActionController::Parameters.new( + claim: { + building_construction_courses: + } + ) + end + + subject do + described_class.new( + journey_session:, + journey:, + params: + ) + end + + describe "validations" do + context "when no option selected" do + it do + is_expected.not_to( + allow_value([""]) + .for(:building_construction_courses) + .with_message("Select all the courses you teach otherwise select you do not teach any of these courses") + ) + end + end + + context "when non-existent injection option selected" do + it do + is_expected.not_to( + allow_value(["foo"]) + .for(:building_construction_courses) + .with_message("Select all the courses you teach otherwise select you do not teach any of these courses") + ) + end + end + end + + describe "#save" do + let(:building_construction_courses) { ["esfa_buildingconstruction", "tlevel_building"] } + + it "updates the journey session" do + expect { expect(subject.save).to be(true) }.to( + change { journey_session.reload.answers.building_construction_courses }.to(building_construction_courses) + ) + end + end +end diff --git a/spec/forms/journeys/further_education_payments/chemistry_courses_form_spec.rb b/spec/forms/journeys/further_education_payments/chemistry_courses_form_spec.rb new file mode 100644 index 0000000000..32c09a230a --- /dev/null +++ b/spec/forms/journeys/further_education_payments/chemistry_courses_form_spec.rb @@ -0,0 +1,55 @@ +require "rails_helper" + +RSpec.describe Journeys::FurtherEducationPayments::ChemistryCoursesForm, type: :model do + let(:journey) { Journeys::FurtherEducationPayments } + let(:journey_session) { create(:further_education_payments_session) } + let(:chemistry_courses) { [""] } + + let(:params) do + ActionController::Parameters.new( + claim: { + chemistry_courses: + } + ) + end + + subject do + described_class.new( + journey_session:, + journey:, + params: + ) + end + + describe "validations" do + context "when no option selected" do + it do + is_expected.not_to( + allow_value([""]) + .for(:chemistry_courses) + .with_message("Select all the courses you teach otherwise select you do not teach any of these courses") + ) + end + end + + context "when non-existent injection option selected" do + it do + is_expected.not_to( + allow_value(["foo"]) + .for(:chemistry_courses) + .with_message("Select all the courses you teach otherwise select you do not teach any of these courses") + ) + end + end + end + + describe "#save" do + let(:chemistry_courses) { ["alevel_chemistry", "gcse_chemistry"] } + + it "updates the journey session" do + expect { expect(subject.save).to be(true) }.to( + change { journey_session.reload.answers.chemistry_courses }.to(chemistry_courses) + ) + end + end +end diff --git a/spec/forms/journeys/further_education_payments/computing_courses_form_spec.rb b/spec/forms/journeys/further_education_payments/computing_courses_form_spec.rb new file mode 100644 index 0000000000..441cd22d10 --- /dev/null +++ b/spec/forms/journeys/further_education_payments/computing_courses_form_spec.rb @@ -0,0 +1,55 @@ +require "rails_helper" + +RSpec.describe Journeys::FurtherEducationPayments::ComputingCoursesForm, type: :model do + let(:journey) { Journeys::FurtherEducationPayments } + let(:journey_session) { create(:further_education_payments_session) } + let(:computing_courses) { [""] } + + let(:params) do + ActionController::Parameters.new( + claim: { + computing_courses: + } + ) + end + + subject do + described_class.new( + journey_session:, + journey:, + params: + ) + end + + describe "validations" do + context "when no option selected" do + it do + is_expected.not_to( + allow_value([""]) + .for(:computing_courses) + .with_message("Select all the courses you teach otherwise select you do not teach any of these courses") + ) + end + end + + context "when non-existent injection option selected" do + it do + is_expected.not_to( + allow_value(["foo"]) + .for(:computing_courses) + .with_message("Select all the courses you teach otherwise select you do not teach any of these courses") + ) + end + end + end + + describe "#save" do + let(:computing_courses) { ["digitalskills_quals", "tlevel_digitalsupport"] } + + it "updates the journey session" do + expect { expect(subject.save).to be(true) }.to( + change { journey_session.reload.answers.computing_courses }.to(computing_courses) + ) + end + end +end diff --git a/spec/forms/journeys/further_education_payments/early_years_courses_form_spec.rb b/spec/forms/journeys/further_education_payments/early_years_courses_form_spec.rb new file mode 100644 index 0000000000..6a20f65c70 --- /dev/null +++ b/spec/forms/journeys/further_education_payments/early_years_courses_form_spec.rb @@ -0,0 +1,55 @@ +require "rails_helper" + +RSpec.describe Journeys::FurtherEducationPayments::EarlyYearsCoursesForm, type: :model do + let(:journey) { Journeys::FurtherEducationPayments } + let(:journey_session) { create(:further_education_payments_session) } + let(:early_years_courses) { [""] } + + let(:params) do + ActionController::Parameters.new( + claim: { + early_years_courses: + } + ) + end + + subject do + described_class.new( + journey_session:, + journey:, + params: + ) + end + + describe "validations" do + context "when no option selected" do + it do + is_expected.not_to( + allow_value([""]) + .for(:early_years_courses) + .with_message("Select all the courses you teach otherwise select you do not teach any of these courses") + ) + end + end + + context "when non-existent injection option selected" do + it do + is_expected.not_to( + allow_value(["foo"]) + .for(:early_years_courses) + .with_message("Select all the courses you teach otherwise select you do not teach any of these courses") + ) + end + end + end + + describe "#save" do + let(:early_years_courses) { ["eylevel2", "eylevel3"] } + + it "updates the journey session" do + expect { expect(subject.save).to be(true) }.to( + change { journey_session.reload.answers.early_years_courses }.to(early_years_courses) + ) + end + end +end diff --git a/spec/forms/journeys/further_education_payments/engineering_manufacturing_courses_form_spec.rb b/spec/forms/journeys/further_education_payments/engineering_manufacturing_courses_form_spec.rb new file mode 100644 index 0000000000..2fd862376a --- /dev/null +++ b/spec/forms/journeys/further_education_payments/engineering_manufacturing_courses_form_spec.rb @@ -0,0 +1,55 @@ +require "rails_helper" + +RSpec.describe Journeys::FurtherEducationPayments::EngineeringManufacturingCoursesForm, type: :model do + let(:journey) { Journeys::FurtherEducationPayments } + let(:journey_session) { create(:further_education_payments_session) } + let(:engineering_manufacturing_courses) { [""] } + + let(:params) do + ActionController::Parameters.new( + claim: { + engineering_manufacturing_courses: + } + ) + end + + subject do + described_class.new( + journey_session:, + journey:, + params: + ) + end + + describe "validations" do + context "when no option selected" do + it do + is_expected.not_to( + allow_value([""]) + .for(:engineering_manufacturing_courses) + .with_message("Select all the courses you teach otherwise select you do not teach any of these courses") + ) + end + end + + context "when non-existent injection option selected" do + it do + is_expected.not_to( + allow_value(["foo"]) + .for(:engineering_manufacturing_courses) + .with_message("Select all the courses you teach otherwise select you do not teach any of these courses") + ) + end + end + end + + describe "#save" do + let(:engineering_manufacturing_courses) { ["esfa_engineering", "esfa_manufacturing"] } + + it "updates the journey session" do + expect { expect(subject.save).to be(true) }.to( + change { journey_session.reload.answers.engineering_manufacturing_courses }.to(engineering_manufacturing_courses) + ) + end + end +end diff --git a/spec/forms/journeys/further_education_payments/hours_teaching_eligible_subjects_form_spec.rb b/spec/forms/journeys/further_education_payments/hours_teaching_eligible_subjects_form_spec.rb new file mode 100644 index 0000000000..1a5de36329 --- /dev/null +++ b/spec/forms/journeys/further_education_payments/hours_teaching_eligible_subjects_form_spec.rb @@ -0,0 +1,58 @@ +require "rails_helper" + +RSpec.describe Journeys::FurtherEducationPayments::HoursTeachingEligibleSubjectsForm, type: :model do + let(:journey) { Journeys::FurtherEducationPayments } + let(:journey_session) { create(:further_education_payments_session) } + + let(:params) do + ActionController::Parameters.new( + claim: { + hours_teaching_eligible_subjects: + } + ) + end + + subject do + described_class.new( + journey_session:, + journey:, + params: + ) + end + + describe "validations" do + let(:hours_teaching_eligible_subjects) { nil } + + it do + is_expected.not_to( + allow_value(nil) + .for(:hours_teaching_eligible_subjects) + .with_message("Select yes if you spend at least half of your timetabled teaching hours teaching these eligible courses") + ) + end + end + + describe "#save" do + context "Yes" do + let(:hours_teaching_eligible_subjects) { true } + + it "updates the journey session" do + expect { expect(subject.save).to be(true) }.to( + change { journey_session.reload.answers.hours_teaching_eligible_subjects } + .to(true) + ) + end + end + + context "No" do + let(:hours_teaching_eligible_subjects) { false } + + it "updates the journey session" do + expect { expect(subject.save).to be(true) }.to( + change { journey_session.reload.answers.hours_teaching_eligible_subjects } + .to(false) + ) + end + end + end +end diff --git a/spec/forms/journeys/further_education_payments/maths_courses_form_spec.rb b/spec/forms/journeys/further_education_payments/maths_courses_form_spec.rb new file mode 100644 index 0000000000..f427b4f8c3 --- /dev/null +++ b/spec/forms/journeys/further_education_payments/maths_courses_form_spec.rb @@ -0,0 +1,55 @@ +require "rails_helper" + +RSpec.describe Journeys::FurtherEducationPayments::MathsCoursesForm, type: :model do + let(:journey) { Journeys::FurtherEducationPayments } + let(:journey_session) { create(:further_education_payments_session) } + let(:maths_courses) { [""] } + + let(:params) do + ActionController::Parameters.new( + claim: { + maths_courses: + } + ) + end + + subject do + described_class.new( + journey_session:, + journey:, + params: + ) + end + + describe "validations" do + context "when no option selected" do + it do + is_expected.not_to( + allow_value([""]) + .for(:maths_courses) + .with_message("Select all the courses you teach otherwise select you do not teach any of these courses") + ) + end + end + + context "when non-existent injection option selected" do + it do + is_expected.not_to( + allow_value(["foo"]) + .for(:maths_courses) + .with_message("Select all the courses you teach otherwise select you do not teach any of these courses") + ) + end + end + end + + describe "#save" do + let(:maths_courses) { ["gcse_maths"] } + + it "updates the journey session" do + expect { expect(subject.save).to be(true) }.to( + change { journey_session.reload.answers.maths_courses }.to(maths_courses) + ) + end + end +end diff --git a/spec/forms/journeys/further_education_payments/physics_courses_form_spec.rb b/spec/forms/journeys/further_education_payments/physics_courses_form_spec.rb new file mode 100644 index 0000000000..3b9bc198ab --- /dev/null +++ b/spec/forms/journeys/further_education_payments/physics_courses_form_spec.rb @@ -0,0 +1,55 @@ +require "rails_helper" + +RSpec.describe Journeys::FurtherEducationPayments::PhysicsCoursesForm, type: :model do + let(:journey) { Journeys::FurtherEducationPayments } + let(:journey_session) { create(:further_education_payments_session) } + let(:physics_courses) { [""] } + + let(:params) do + ActionController::Parameters.new( + claim: { + physics_courses: + } + ) + end + + subject do + described_class.new( + journey_session:, + journey:, + params: + ) + end + + describe "validations" do + context "when no option selected" do + it do + is_expected.not_to( + allow_value([""]) + .for(:physics_courses) + .with_message("Select all the courses you teach otherwise select you do not teach any of these courses") + ) + end + end + + context "when non-existent injection option selected" do + it do + is_expected.not_to( + allow_value(["foo"]) + .for(:physics_courses) + .with_message("Select all the courses you teach otherwise select you do not teach any of these courses") + ) + end + end + end + + describe "#save" do + let(:physics_courses) { ["alevel_physics", "gcse_physics"] } + + it "updates the journey session" do + expect { expect(subject.save).to be(true) }.to( + change { journey_session.reload.answers.physics_courses }.to(physics_courses) + ) + end + end +end diff --git a/spec/forms/journeys/further_education_payments/subjects_taught_form_spec.rb b/spec/forms/journeys/further_education_payments/subjects_taught_form_spec.rb index 22f5c75266..355d60dca5 100644 --- a/spec/forms/journeys/further_education_payments/subjects_taught_form_spec.rb +++ b/spec/forms/journeys/further_education_payments/subjects_taught_form_spec.rb @@ -2,7 +2,9 @@ RSpec.describe Journeys::FurtherEducationPayments::SubjectsTaughtForm, type: :model do let(:journey) { Journeys::FurtherEducationPayments } - let(:journey_session) { create(:further_education_payments_session) } + let(:journey_session) { create(:further_education_payments_session, answers:) } + let(:answers) { build(:further_education_payments_answers, answers_hash) } + let(:answers_hash) { {} } let(:subjects_taught) { [] } let(:params) do @@ -48,12 +50,70 @@ end describe "#save" do - let(:subjects_taught) { ["chemistry", "mathematics"] } + let(:subjects_taught) { ["chemistry", "maths"] } it "updates the journey session" do expect { expect(subject.save).to be(true) }.to( - change { journey_session.reload.answers.subjects_taught }.to(["chemistry", "mathematics"]) + change { journey_session.reload.answers.subjects_taught }.to(["chemistry", "maths"]) ) end + + context "when changing some answers" do + let(:answers_hash) do + { + subjects_taught: %w[maths physics], + maths_courses: %w[esfa], + physics_courses: %w[alevel_physics] + } + end + + let(:subjects_taught) { %w[chemistry maths] } + + it "resets dependent answers" do + expect { expect(subject.save).to be(true) }.to( + change { journey_session.reload.answers.subjects_taught }.to(subjects_taught) + .and(change { journey_session.reload.answers.physics_courses }.to([]) + .and(not_change { journey_session.reload.answers.maths_courses })) + ) + end + end + + context "when changing all answers" do + let(:answers_hash) do + { + subjects_taught: %w[ + building_construction + chemistry + computing + early_years + engineering_manufacturing + maths + physics + ], + building_construction_courses: %w[none], + chemistry_courses: %w[none], + computing_courses: %w[none], + early_years_courses: %w[none], + engineering_manufacturing_courses: %w[none], + maths_courses: %w[none], + physics_courses: %w[none] + } + end + + let(:subjects_taught) { %w[none] } + + it "resets dependent answers" do + expect { expect(subject.save).to be(true) }.to( + change { journey_session.reload.answers.subjects_taught }.to(subjects_taught) + .and(change { journey_session.reload.answers.building_construction_courses }.to([]) + .and(change { journey_session.reload.answers.chemistry_courses }.to([]) + .and(change { journey_session.reload.answers.computing_courses }.to([]) + .and(change { journey_session.reload.answers.early_years_courses }.to([]) + .and(change { journey_session.reload.answers.engineering_manufacturing_courses }.to([]) + .and(change { journey_session.reload.answers.maths_courses }.to([]) + .and(change { journey_session.reload.answers.physics_courses }.to([])))))))) + ) + end + end end end diff --git a/spec/forms/journeys/further_education_payments/teaching_hours_per_week_next_term_form_spec.rb b/spec/forms/journeys/further_education_payments/teaching_hours_per_week_next_term_form_spec.rb new file mode 100644 index 0000000000..c197b64fdb --- /dev/null +++ b/spec/forms/journeys/further_education_payments/teaching_hours_per_week_next_term_form_spec.rb @@ -0,0 +1,48 @@ +require "rails_helper" + +RSpec.describe Journeys::FurtherEducationPayments::TeachingHoursPerWeekNextTermForm, type: :model do + let(:journey) { Journeys::FurtherEducationPayments } + let(:journey_session) { create(:further_education_payments_session, answers:) } + let(:answers) { build(:further_education_payments_answers, answers_hash) } + let(:college) { create(:school) } + let(:answers_hash) do + {school_id: college.id} + end + let(:teaching_hours_per_week_next_term) { nil } + + let(:params) do + ActionController::Parameters.new( + claim: { + teaching_hours_per_week_next_term: + } + ) + end + + subject do + described_class.new( + journey_session:, + journey:, + params: + ) + end + + describe "validations" do + it do + is_expected.not_to( + allow_value(nil) + .for(:teaching_hours_per_week_next_term) + .with_message("Select yes if you are timetabled to teach at least 2.5 hours next term otherwise select you are not") + ) + end + end + + describe "#save" do + let(:teaching_hours_per_week_next_term) { "at_least_2_5" } + + it "updates the journey session" do + expect { expect(subject.save).to be(true) }.to( + change { journey_session.reload.answers.teaching_hours_per_week_next_term }.to(teaching_hours_per_week_next_term) + ) + end + end +end diff --git a/spec/forms/journeys/get_a_teacher_relocation_payment/claim_submission_form_spec.rb b/spec/forms/journeys/get_a_teacher_relocation_payment/claim_submission_form_spec.rb index f9bbba704f..6d7c52ab0c 100644 --- a/spec/forms/journeys/get_a_teacher_relocation_payment/claim_submission_form_spec.rb +++ b/spec/forms/journeys/get_a_teacher_relocation_payment/claim_submission_form_spec.rb @@ -88,6 +88,10 @@ eligibility_answers.each do |attribute, value| expect(eligibility.public_send(attribute)).to eq(value) end + + expect(eligibility.award_amount).to eq( + Policies::InternationalRelocationPayments.award_amount + ) end end end diff --git a/spec/models/eligible_fe_providers_importer_spec.rb b/spec/models/eligible_fe_providers_importer_spec.rb new file mode 100644 index 0000000000..d865dc5775 --- /dev/null +++ b/spec/models/eligible_fe_providers_importer_spec.rb @@ -0,0 +1,88 @@ +require "rails_helper" + +RSpec.describe EligibleFeProvidersImporter do + subject { described_class.new(file, academic_year) } + + let(:academic_year) { AcademicYear.current } + let(:file) { Tempfile.new } + let(:correct_headers) { described_class.mandatory_headers.join(",") + "\n" } + + def to_row(hash) + [ + hash[:ukprn], + hash[:max_award_amount], + hash[:lower_award_amount] + ].join(",") + "\n" + end + + describe "#run" do + context "when incorrect headers" do + before do + file.write "incorrect,headers,here,here" + file.close + end + + it "has errors" do + subject.run + + expect(subject.errors).to be_present + expect(subject.errors).to include("The selected file is missing some expected columns: ukprn, max_award_amount, lower_award_amount") + end + end + + context "when csv has no rows" do + before do + file.write correct_headers + file.close + end + + it "has no errors" do + subject.run + + expect(subject.errors).to be_empty + end + + it "does not add any any records" do + expect { subject.run }.not_to change { EligibleFeProvider.count } + end + + context "when there are existing records" do + before do + create(:eligible_fe_provider) + create(:eligible_fe_provider, academic_year: AcademicYear.next) + end + + it "deletes existing records for academic year" do + expect { subject.run }.to change { EligibleFeProvider.count }.to(1) + end + end + end + + context "with valid data" do + before do + file.write correct_headers + + 3.times do + file.write to_row(attributes_for(:eligible_fe_provider)) + end + + file.close + end + + it "imports new records" do + expect { subject.run }.to change { EligibleFeProvider.count }.by(3) + end + + context "when there are existing records" do + before do + create(:eligible_fe_provider) + create(:eligible_fe_provider, academic_year: AcademicYear.next) + end + + it "deletes them with new records" do + expect { subject.run }.to change { EligibleFeProvider.count }.by(2) + end + end + end + end +end diff --git a/spec/models/journeys/further_education_payments/answers_presenter_spec.rb b/spec/models/journeys/further_education_payments/answers_presenter_spec.rb index 892202376c..86dfcfa0e0 100644 --- a/spec/models/journeys/further_education_payments/answers_presenter_spec.rb +++ b/spec/models/journeys/further_education_payments/answers_presenter_spec.rb @@ -14,7 +14,7 @@ let(:contract_type) { "permanent" } let(:teaching_hours_per_week) { "more_than_12" } let(:further_education_teaching_start_year) { 2023 } - let(:subjects_taught) { ["chemistry", "mathematics"] } + let(:subjects_taught) { ["chemistry", "maths"] } let(:half_teaching_hours) { true } let(:teaching_qualification) { "yes" } let(:subject_to_formal_performance_action) { false } @@ -44,7 +44,7 @@ ["What type of contract do you have with #{college.name}?", "Permanent contract", "contract-type"], ["On average, how many hours per week are you timetabled to teach at #{college.name} during the current term?", "More than 12 hours per week", "teaching-hours-per-week"], ["Which academic year did you start teaching in further education (FE) in England?", "September 2023 to August 2024", "further-education-teaching-start-year"], - ["Which subject areas do you teach?", "

Chemistry

Mathematics

", "subjects-taught"], + ["Which subject areas do you teach?", "

Chemistry

Maths

", "subjects-taught"], ["Are at least half of your timetabled teaching hours spent teaching 16 to 19-year-olds, including those up to age 25 with an Education, Health and Care Plan (EHCP)?", "Yes", "half-teaching-hours"], ["Do you have a teaching qualification?", "Yes", "teaching-qualification"], ["Have any performance measures been started against you?", "No", "poor-performance"], @@ -66,7 +66,7 @@ end context "subjects-taught - just one" do - let(:subjects_taught) { %w[building_and_construction] } + let(:subjects_taught) { %w[building_construction] } it { is_expected.to include([ @@ -78,12 +78,12 @@ end context "subjects-taught - all of them" do - let(:subjects_taught) { %w[building_and_construction chemistry computing early_years engineering_and_manufacturing mathematics physics] } + let(:subjects_taught) { %w[building_construction chemistry computing early_years engineering_manufacturing maths physics] } it { is_expected.to include([ "Which subject areas do you teach?", - "

Building and construction

Chemistry

Computing, including digital and ICT

Early years

Engineering and manufacturing, including transport engineering and electronics

Mathematics

Physics

", + "

Building and construction

Chemistry

Computing, including digital and ICT

Early years

Engineering and manufacturing, including transport engineering and electronics

Maths

Physics

", "subjects-taught" ]) } diff --git a/spec/models/journeys/get_a_teacher_relocation_payment/answers_presenter_spec.rb b/spec/models/journeys/get_a_teacher_relocation_payment/answers_presenter_spec.rb index 3e8f58f4ed..1afd702632 100644 --- a/spec/models/journeys/get_a_teacher_relocation_payment/answers_presenter_spec.rb +++ b/spec/models/journeys/get_a_teacher_relocation_payment/answers_presenter_spec.rb @@ -16,6 +16,7 @@ :with_teacher_application_route, :with_state_funded_secondary_school, :with_current_school, + :with_headteacher_details, :with_one_year_contract, :with_start_date, :with_subject, @@ -32,15 +33,20 @@ "I am employed as a teacher in a school in England", "application-route" ], + [ + "Are you employed by an English state secondary school?", + "Yes", + "state-funded-secondary-school" + ], [ "Which school are you currently employed to teach at?", answers.current_school.name, "current-school" ], [ - "Are you employed by an English state secondary school?", - "Yes", - "state-funded-secondary-school" + "Enter the name of the headteacher of the school where you are employed as a teacher", + "Seymour Skinner", + "headteacher-details" ], [ "Are you employed on a contract lasting at least one year?", @@ -97,25 +103,4 @@ ) end end - - describe "#employment_answers" do - subject { presenter.employment_answers } - - let(:answers) do - build( - :get_a_teacher_relocation_payment_answers, - :with_employment_details - ) - end - - it do - is_expected.to include( - [ - "Enter the name of the headteacher of the school where you are employed as a teacher", - "Seymour Skinner", - "headteacher-details" - ] - ) - end - end end diff --git a/spec/models/policies/further_education_payments/policy_eligibility_checker_spec.rb b/spec/models/policies/further_education_payments/policy_eligibility_checker_spec.rb index 5b93b7917e..99c90d21d3 100644 --- a/spec/models/policies/further_education_payments/policy_eligibility_checker_spec.rb +++ b/spec/models/policies/further_education_payments/policy_eligibility_checker_spec.rb @@ -25,11 +25,39 @@ build(:further_education_payments_answers, taught_at_least_one_term: false) end - it "is ineligble as :lack_teaching_responsibilities" do + it "is ineligble as :must_teach_at_least_one_term" do expect(subject).to be_ineligible expect(subject.status).to eql(:ineligible) expect(subject.ineligibility_reason).to eql(:must_teach_at_least_one_term) end end + + context "when ineligible as lacking subjects taught" do + let(:answers) do + build(:further_education_payments_answers, subjects_taught: ["none"]) + end + + it "is ineligble as :subject" do + expect(subject).to be_ineligible + expect(subject.status).to eql(:ineligible) + expect(subject.ineligibility_reason).to eql(:subject) + end + end + + context "when all courses are ineligible" do + let(:answers) do + build( + :further_education_payments_answers, + subjects_taught: ["building_construction"], + building_construction_courses: ["none"] + ) + end + + it "is ineligble as :lack_teaching_responsibilities" do + expect(subject).to be_ineligible + expect(subject.status).to eql(:ineligible) + expect(subject.ineligibility_reason).to eql(:courses) + end + end end end diff --git a/spec/models/policies/international_relocation_payments/eligibility_admin_answers_presenter_spec.rb b/spec/models/policies/international_relocation_payments/eligibility_admin_answers_presenter_spec.rb index 7dba901327..291234d846 100644 --- a/spec/models/policies/international_relocation_payments/eligibility_admin_answers_presenter_spec.rb +++ b/spec/models/policies/international_relocation_payments/eligibility_admin_answers_presenter_spec.rb @@ -1,13 +1,60 @@ require "rails_helper" RSpec.describe Policies::InternationalRelocationPayments::EligibilityAdminAnswersPresenter, type: :model do - let(:claim) { build(:claim, :submittable, policy: Policies::InternationalRelocationPayments, academic_year: "2021/2022") } + describe "#answers" do + subject { described_class.new(eligibility).answers } - subject(:presenter) { described_class.new(claim.eligibility) } + let(:school) { create(:school) } - describe "#answers" do - it "returns an array of questions and answers for displaying to service operator" do - expect(presenter.answers).to eq [[I18n.t("admin.current_school"), presenter.display_school(claim.eligibility.current_school)]] + let(:eligibility) do + build( + :international_relocation_payments_eligibility, + nationality: "American", + passport_number: "123456789", + current_school: school, + subject: "physics", + school_headteacher_name: "Principal Skinner", + start_date: Date.new(2024, 3, 1), + visa_type: "British National (Overseas) visa", + date_of_entry: Date.new(2024, 2, 1) + ) + end + + it do + is_expected.to include( + [ + "Nationality", + "American" + ], + [ + "Passport number", + "123456789" + ], + [ + "Current school", + /#{school.name}/ + ], + [ + "Subject", + "Physics" + ], + [ + "School headteacher name", + "Principal Skinner" + ], + [ + "Contract start date", + "1 March 2024" + ], + [ + "Visa type", + "British National (Overseas) visa" + ], + [ + "Date of entry", + "1 February 2024" + ] + ) end end end diff --git a/spec/smoke/start_a_claim_spec.rb b/spec/smoke/start_a_claim_spec.rb deleted file mode 100644 index f334c41f75..0000000000 --- a/spec/smoke/start_a_claim_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -require "rails_helper" - -RSpec.describe "Start a claim", :smoke, type: :feature do - # To test this locally you will need to add to your .env file: - # - # SMOKE_TEST_APP_HOST - # BASIC_AUTH_USERNAME - # BASIC_AUTH_PASSWORD - - scenario "User starts a claim" do - visit url_with_basic_auth - expect(page).to have_text("Teachers: claim back your student loan repayments") - end - - def url_with_basic_auth - host = ENV.fetch("SMOKE_TEST_APP_HOST") - path = new_claim_path(Journeys::TeacherStudentLoanReimbursement::ROUTING_NAME) - uri = URI.join(host, path) - - uri.user = ENV.fetch("BASIC_AUTH_USERNAME", nil) - uri.password = ENV.fetch("BASIC_AUTH_PASSWORD", nil) - uri.to_s - end -end diff --git a/spec/smoke/visit_admin_spec.rb b/spec/smoke/visit_admin_spec.rb new file mode 100644 index 0000000000..c9d66cd904 --- /dev/null +++ b/spec/smoke/visit_admin_spec.rb @@ -0,0 +1,30 @@ +require "rails_helper" + +RSpec.describe "Visit admin", :smoke, type: :feature do + # To test this locally you will need to add to your .env file: + # + # SMOKE_TEST_APP_HOST + # BASIC_AUTH_USERNAME + # BASIC_AUTH_PASSWORD + + scenario "User visits admin" do + visit url_with_basic_auth + expect(page).to have_text(I18n.t("service_name")) + end + + def url_with_basic_auth + host = ENV.fetch("SMOKE_TEST_APP_HOST") + path = admin_root_path + uri = URI.join(host, path) + + username = ENV.fetch("BASIC_AUTH_USERNAME", nil) + password = ENV.fetch("BASIC_AUTH_PASSWORD", nil) + + if username.present? && password.present? + uri.user = username + uri.password = password + end + + uri.to_s + end +end diff --git a/spec/support/steps/journey_configuration.rb b/spec/support/steps/journey_configuration.rb new file mode 100644 index 0000000000..af552fccb5 --- /dev/null +++ b/spec/support/steps/journey_configuration.rb @@ -0,0 +1,3 @@ +def when_further_education_payments_journey_configuration_exists + create(:journey_configuration, :further_education_payments) +end diff --git a/terraform/application/application.tf b/terraform/application/application.tf index 9818895f82..d4afd87ec6 100644 --- a/terraform/application/application.tf +++ b/terraform/application/application.tf @@ -13,10 +13,10 @@ module "application_configuration" { config_variables = merge( local.app_env_values, { - ENVIRONMENT_NAME = var.environment - PGSSLMODE = local.postgres_ssl_mode + ENVIRONMENT_NAME = var.environment + PGSSLMODE = local.postgres_ssl_mode CANONICAL_HOSTNAME = local.canonical_hostname - }) + }) secret_variables = { DATABASE_URL = module.postgres.url } @@ -39,7 +39,9 @@ module "web_application" { docker_image = var.docker_image command = var.startup_command - replicas = var.web_replicas + replicas = var.web_replicas + + enable_logit = var.enable_logit } module "worker_application" { @@ -58,4 +60,8 @@ module "worker_application" { docker_image = var.docker_image command = var.worker_command + + replicas = var.worker_replicas + + enable_logit = var.enable_logit } diff --git a/terraform/application/config/production.tfvars.json b/terraform/application/config/production.tfvars.json new file mode 100644 index 0000000000..51b2bc1096 --- /dev/null +++ b/terraform/application/config/production.tfvars.json @@ -0,0 +1,22 @@ +{ + "cluster": "production", + "namespace": "srtl-production", + "config": "production", + "environment": "production", + "canonical_hostname": "www.claim-additional-teaching-payment.service.gov.uk", + "web_replicas": 2, + "worker_replicas": 2, + "startup_command": ["/bin/sh", "-c", "bin/rails server -b 0.0.0.0"], + "worker_command": ["/bin/sh", "-c", "bin/bundle exec bin/delayed_job run -n 1"], + "postgres_flexible_server_sku": "GP_Standard_D2ds_v4", + "postgres_enable_high_availability": true, + "enable_postgres_backup_storage": true, + "azure_maintenance_window": { + "day_of_week": 0, + "start_hour": 3, + "start_minute": 0 + }, + "enable_monitoring": true, + "statuscake_contact_groups": [195955, 282453], + "external_url": "https://www.claim-additional-teaching-payment.service.gov.uk/healthcheck" +} diff --git a/terraform/application/config/production_Terrafile b/terraform/application/config/production_Terrafile new file mode 100644 index 0000000000..5b2b118f00 --- /dev/null +++ b/terraform/application/config/production_Terrafile @@ -0,0 +1,3 @@ +aks: + source: "https://github.com/DFE-Digital/terraform-modules" + version: "stable" diff --git a/terraform/application/config/production_app_env.yml b/terraform/application/config/production_app_env.yml new file mode 100644 index 0000000000..65f3b3fe10 --- /dev/null +++ b/terraform/application/config/production_app_env.yml @@ -0,0 +1,19 @@ +--- +DFE_SIGN_IN_API_CLIENT_ID: teacherpayments +DFE_SIGN_IN_API_ENDPOINT: https://api.signin.education.gov.uk +DFE_SIGN_IN_IDENTIFIER: teacherpayments +DFE_SIGN_IN_ISSUER: https://oidc.signin.education.gov.uk:443 +DFE_SIGN_IN_REDIRECT_BASE_URL: https://www.claim-additional-teaching-payment.service.gov.uk + +DQT_API_URL: https://teacher-qualifications-api.education.gov.uk/v1 +DQT_BASE_URL: https://api-customerengagement.platform.education.gov.uk/dqt-crm/v1/ + +HMRC_API_BASE_URL: https://api.service.hmrc.gov.uk +HMRC_API_BANK_VALIDATION_ENABLED: true + +ORDNANCE_SURVEY_API_BASE_URL: https://api.os.uk + +TID_BASE_URL: https://claim-additional-teaching-payment.service.gov.uk/additional-payments/claim +TID_SIGN_IN_API_ENDPOINT: https://teaching-identity.education.gov.uk/ +TID_SIGN_IN_CLIENT_ID: claim +TID_SIGN_IN_ISSUER: https://teaching-identity.education.gov.uk/ diff --git a/terraform/application/config/review.tfvars.json b/terraform/application/config/review.tfvars.json index 39f0b0d215..496c0b3474 100644 --- a/terraform/application/config/review.tfvars.json +++ b/terraform/application/config/review.tfvars.json @@ -5,5 +5,6 @@ "deploy_azure_backing_services": false, "enable_postgres_ssl": false, "startup_command": ["/bin/sh", "-c", "bin/rails server -b 0.0.0.0"], - "worker_command": ["/bin/sh", "-c", "bin/bundle exec bin/delayed_job run -n 4"] + "worker_command": ["/bin/sh", "-c", "bin/bundle exec bin/delayed_job run -n 1"], + "enable_logit": true } diff --git a/terraform/application/config/review_app_env.yml b/terraform/application/config/review_app_env.yml index 1376e72ede..0c3804dd1c 100644 --- a/terraform/application/config/review_app_env.yml +++ b/terraform/application/config/review_app_env.yml @@ -19,3 +19,4 @@ SUPPRESS_DFE_ANALYTICS_INIT: true TID_SIGN_IN_API_ENDPOINT: https://preprod.teaching-identity.education.gov.uk:433 TID_SIGN_IN_CLIENT_ID: claim TID_SIGN_IN_ISSUER: https://preprod.teaching-identity.education.gov.uk/ +TID_BASE_URL: https://claim-additional-payments-for-teaching-review-*.test.teacherservices.cloud/additional-payments/claim diff --git a/terraform/application/config/test.tfvars.json b/terraform/application/config/test.tfvars.json index 31970e11c3..2549db46f7 100644 --- a/terraform/application/config/test.tfvars.json +++ b/terraform/application/config/test.tfvars.json @@ -3,8 +3,12 @@ "namespace": "srtl-test", "config": "test", "environment": "test", - "canonical_hostname": "claim-additional-payments-for-teaching-test-web.test.teacherservices.cloud", + "canonical_hostname": "test.claim-additional-teaching-payment.service.gov.uk", "web_replicas": 2, "startup_command": ["/bin/sh", "-c", "bin/rails server -b 0.0.0.0"], - "worker_command": ["/bin/sh", "-c", "bin/bundle exec bin/delayed_job run -n 1"] + "worker_command": ["/bin/sh", "-c", "bin/bundle exec bin/delayed_job run -n 1"], + "enable_monitoring": true, + "statuscake_contact_groups": [195955, 282453], + "external_url": "https://test.claim-additional-teaching-payment.service.gov.uk/healthcheck", + "enable_logit": true } diff --git a/terraform/application/config/test_app_env.yml b/terraform/application/config/test_app_env.yml index 395608fa0f..6d52c73112 100644 --- a/terraform/application/config/test_app_env.yml +++ b/terraform/application/config/test_app_env.yml @@ -3,6 +3,7 @@ DFE_SIGN_IN_API_CLIENT_ID: teacherpayments DFE_SIGN_IN_API_ENDPOINT: https://test-api.signin.education.gov.uk/ DFE_SIGN_IN_IDENTIFIER: teacherpayments DFE_SIGN_IN_ISSUER: https://test-oidc.signin.education.gov.uk:443 +DFE_SIGN_IN_REDIRECT_BASE_URL: https://test.claim-additional-teaching-payment.service.gov.uk DQT_API_URL: https://test.teacher-qualifications-api.education.gov.uk/v1 DQT_BASE_URL: https://test-api-customerengagement.platform.education.gov.uk/dqt-crm/v1/ @@ -14,6 +15,7 @@ ORDNANCE_SURVEY_API_BASE_URL: https://api.os.uk SUPPRESS_DFE_ANALYTICS_INIT: true +TID_BASE_URL: https://test.claim-additional-teaching-payment.service.gov.uk/additional-payments/claim TID_SIGN_IN_API_ENDPOINT: https://preprod.teaching-identity.education.gov.uk:433 TID_SIGN_IN_CLIENT_ID: claim TID_SIGN_IN_ISSUER: https://preprod.teaching-identity.education.gov.uk/ diff --git a/terraform/application/database.tf b/terraform/application/database.tf index 957b6c2b82..1d363336c1 100644 --- a/terraform/application/database.tf +++ b/terraform/application/database.tf @@ -1,16 +1,19 @@ module "postgres" { source = "./vendor/modules/aks//aks/postgres" - namespace = var.namespace - environment = var.environment - azure_resource_prefix = var.azure_resource_prefix - service_name = var.service_name - service_short = var.service_short - config_short = var.config_short - cluster_configuration_map = module.cluster_data.configuration_map - use_azure = var.deploy_azure_backing_services - azure_enable_monitoring = var.enable_monitoring - azure_enable_backup_storage = var.enable_postgres_backup_storage - azure_extensions = ["pg_trgm", "pgcrypto", "plpgsql"] - server_version = "16" + namespace = var.namespace + environment = var.environment + azure_resource_prefix = var.azure_resource_prefix + service_name = var.service_name + service_short = var.service_short + config_short = var.config_short + cluster_configuration_map = module.cluster_data.configuration_map + use_azure = var.deploy_azure_backing_services + azure_enable_monitoring = var.enable_monitoring + azure_enable_backup_storage = var.enable_postgres_backup_storage + azure_extensions = ["pg_trgm", "pgcrypto", "plpgsql"] + server_version = "16" + azure_sku_name = var.postgres_flexible_server_sku + azure_enable_high_availability = var.postgres_enable_high_availability + azure_maintenance_window = var.azure_maintenance_window } diff --git a/terraform/application/statuscake.tf b/terraform/application/statuscake.tf index 840f7a8ad6..be1b3f03ef 100644 --- a/terraform/application/statuscake.tf +++ b/terraform/application/statuscake.tf @@ -1,12 +1,10 @@ -# TODO: Uncomment when needed then follow these steps: https://github.com/DFE-Digital/teacher-services-cloud/blob/main/documentation/onboard-service.md#configure-statuscake-credentials +module "statuscake" { + count = var.enable_monitoring ? 1 : 0 -# module "statuscake" { -# count = var.enable_monitoring ? 1 : 0 + source = "./vendor/modules/aks//monitoring/statuscake" -# source = "./vendor/modules/aks//monitoring/statuscake" + uptime_urls = compact([module.web_application.probe_url, var.external_url]) + ssl_urls = compact([var.external_url]) -# uptime_urls = compact([module.web_application.probe_url, var.external_url]) -# ssl_urls = compact([var.external_url]) - -# contact_groups = var.statuscake_contact_groups -# } + contact_groups = var.statuscake_contact_groups +} diff --git a/terraform/application/variables.tf b/terraform/application/variables.tf index d2e6ae8677..4453323375 100644 --- a/terraform/application/variables.tf +++ b/terraform/application/variables.tf @@ -62,12 +62,31 @@ variable "canonical_hostname" { } variable "web_replicas" { description = "Number of replicas of the web app" - default = 1 + default = 1 +} +variable "worker_replicas" { + description = "Number of replicas of the worker" + default = 1 +} +variable "azure_maintenance_window" { + default = null +} +variable "postgres_flexible_server_sku" { + default = "B_Standard_B1ms" +} +variable "postgres_enable_high_availability" { + default = false +} +variable "enable_logit" { + type = bool + default = false + description = "A boolean to indicate whether to enable sending container logs to logit.io" + nullable = false } locals { - postgres_ssl_mode = var.enable_postgres_ssl ? "require" : "disable" - canonical_hostname = var.canonical_hostname != null ? var.canonical_hostname : "${var.service_name}-${var.environment}-web.test.teacherservices.cloud" + postgres_ssl_mode = var.enable_postgres_ssl ? "require" : "disable" + canonical_hostname = var.canonical_hostname != null ? var.canonical_hostname : "${var.service_name}-${var.environment}-web.test.teacherservices.cloud" app_env_values_from_yml = yamldecode(file("${path.module}/config/${var.config}_app_env.yml")) - app_env_values = merge(local.app_env_values_from_yml) + app_env_values = merge(local.app_env_values_from_yml) } diff --git a/terraform/domains/environment_domains/config/production.tfvars.json b/terraform/domains/environment_domains/config/production.tfvars.json index b752b31c6d..af1d6fcfe0 100644 --- a/terraform/domains/environment_domains/config/production.tfvars.json +++ b/terraform/domains/environment_domains/config/production.tfvars.json @@ -11,7 +11,7 @@ "/assets/*" ], "environment_short": "pd", - "origin_hostname": "s118p01-app-as.azurewebsites.net", + "origin_hostname": "claim-additional-payments-for-teaching-production-web.teacherservices.cloud", "redirect_rules": [{ "from-domain": "apex", "to-domain": "www.claim-additional-teaching-payment.service.gov.uk" diff --git a/terraform/domains/environment_domains/config/test.tfvars.json b/terraform/domains/environment_domains/config/test.tfvars.json index 80327c3c91..9d3590b839 100644 --- a/terraform/domains/environment_domains/config/test.tfvars.json +++ b/terraform/domains/environment_domains/config/test.tfvars.json @@ -10,7 +10,7 @@ "/assets/*" ], "environment_short": "ts", - "origin_hostname": "s118t01-app-as.azurewebsites.net" + "origin_hostname": "claim-additional-payments-for-teaching-test-web.test.teacherservices.cloud" } } } diff --git a/yarn.lock b/yarn.lock index 059a348176..ff1ad66687 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24,7 +24,7 @@ govuk-frontend@^5.4.0: resolved "https://registry.yarnpkg.com/govuk-frontend/-/govuk-frontend-5.4.0.tgz#8f2e0b55ef7c7552a1efe68c7b40ff1b4a393e72" integrity sha512-F3YwQYrYQqIPfNxsoph6O78Ey1unCB6cy6omx8KeWY9G504lWZFBSIaiUCma1jNLw9bOUU7Ui+tXG09jjqy0Mw== -prettier@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.2.tgz#03ff86dc7c835f2d2559ee76876a3914cec4a90a" - integrity sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA== +prettier@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" + integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==