diff --git a/app/controllers/journeys/additional_payments_for_teaching/reminders_controller.rb b/app/controllers/journeys/additional_payments_for_teaching/reminders_controller.rb deleted file mode 100644 index 8c75859477..0000000000 --- a/app/controllers/journeys/additional_payments_for_teaching/reminders_controller.rb +++ /dev/null @@ -1,96 +0,0 @@ -module Journeys - module AdditionalPaymentsForTeaching - class RemindersController < BasePublicController - include PartOfClaimJourney - - after_action :clear_sessions, only: :show - helper_method :current_reminder - - include FormSubmittable - include RemindersFormCallbacks - - private - - def load_form_if_exists - @form ||= AdditionalPaymentsForTeaching::FORMS.dig( - "reminders", params[:slug] - )&.new(reminder: current_reminder, journey: Journeys::AdditionalPaymentsForTeaching, journey_session:, params:) - end - - def slugs - journey.slug_sequence::REMINDER_SLUGS - end - - def next_slug - slugs[current_slug_index + 1] - end - - def current_slug - slugs[current_slug_index] - end - - def current_slug_index - slugs.index(params[:slug]) || 0 - end - - def current_template - "reminders/#{current_slug.underscore}" - end - - def current_reminder - @current_reminder ||= - reminder_from_session || - build_reminder_from_claim || - default_reminder - end - - def reminder_from_session - return unless answers&.reminder_id - - Reminder.find(answers.reminder_id) - end - - def submitted_claim - @submitted_claim ||= Claim.includes(:eligibility).find_by(id: session[:submitted_claim_id]) - end - - def build_reminder_from_claim - return unless model_for_reminder_attributes - - Reminder.new( - full_name: model_for_reminder_attributes.full_name, - email_address: model_for_reminder_attributes.email_address, - itt_academic_year: next_academic_year, - itt_subject: model_for_reminder_attributes.eligible_itt_subject, - email_verified: model_for_reminder_attributes.email_verified? # allows the OTP to be skipped if already verified - ) - end - - # Reminders can be set for in progress and submitted claims - # We can tell if we're setting a reminder for a submitted claim as the - # journey session will be nil given that we clear it on claim submission. - def model_for_reminder_attributes - @model_for_reminder_attributes ||= answers || submitted_claim - end - - def send_to_start? - model_for_reminder_attributes.nil? - end - - # Fallback reminder will set reminder date to the next academic year - def default_reminder - Reminder.new(itt_academic_year: next_academic_year) - end - - def next_academic_year - journey_configuration.current_academic_year + 1 - end - - def clear_sessions - return unless current_slug == "set" - - session.delete(journey_session_key) - end - end - end -end diff --git a/app/controllers/journeys/additional_payments_for_teaching/reminders_form_callbacks.rb b/app/controllers/journeys/additional_payments_for_teaching/reminders_form_callbacks.rb deleted file mode 100644 index fe5c115279..0000000000 --- a/app/controllers/journeys/additional_payments_for_teaching/reminders_form_callbacks.rb +++ /dev/null @@ -1,81 +0,0 @@ -module Journeys - module AdditionalPaymentsForTeaching - module RemindersFormCallbacks - def personal_details_before_show - try_mailer { set_a_reminder_immediately_if_possible } - end - - def email_verification_before_show - try_mailer { set_a_reminder_immediately_if_possible } - end - - def email_verification_before_update - inject_sent_one_time_password_at_into_the_form - end - - def personal_details_after_form_save_success - answers.reminder_id = current_reminder.to_param - answers.email_verification_secret = ROTP::Base32.random - journey_session.save! - try_mailer { send_verification_email } || return - redirect_to_next_slug - end - - def email_verification_after_form_save_success - try_mailer { send_reminder_set_email } || return - redirect_to_next_slug - end - - private - - def set_a_reminder_immediately_if_possible - return if current_reminder.persisted? - - if current_reminder.email_verified? && current_reminder.save - ReminderMailer.reminder_set(current_reminder).deliver_now - - redirect_to reminder_path(current_journey_routing_name, "set") - end - end - - def inject_sent_one_time_password_at_into_the_form - params[:form]&.[]=(:sent_one_time_password_at, session[:sent_one_time_password_at]) - end - - def send_verification_email - otp = OneTimePassword::Generator.new(secret: answers.email_verification_secret) - ReminderMailer.email_verification(current_reminder, otp.code).deliver_now - session[:sent_one_time_password_at] = Time.now - end - - def send_reminder_set_email - ReminderMailer.reminder_set(current_reminder).deliver_now - end - - def try_mailer(&block) - yield if block - true - rescue Notifications::Client::BadRequestError => e - if notify_email_error?(e.message) - render_template_for_current_slug - false - else - raise - end - end - - def notify_email_error?(msg) - case msg - when "ValidationError: email_address is a required property" - @form.errors.add(:email_address, :invalid, message: @form.i18n_errors_path(:"email_address.invalid")) - true - when "BadRequestError: Can’t send to this recipient using a team-only API key" - @form.errors.add(:email_address, :invalid, message: @form.i18n_errors_path(:"email_address.unauthorised")) - true - else - false - end - end - end - end -end diff --git a/app/controllers/reminders_controller.rb b/app/controllers/reminders_controller.rb index 057c5afc5d..fa924fd1cb 100644 --- a/app/controllers/reminders_controller.rb +++ b/app/controllers/reminders_controller.rb @@ -4,7 +4,11 @@ class RemindersController < BasePublicController def show @form = form_from_slug - render view_file + if @form.set_reminder_from_claim + redirect_to independent_reminder_path(journey: journey::ROUTING_NAME, slug: "confirmation") + else + render view_file + end end def update @@ -70,7 +74,8 @@ def form_from_slug form_class_from_slug.new( journey_session:, journey:, - params: + params:, + session: ) end end diff --git a/app/forms/journeys/additional_payments_for_teaching/reminders/email_verification_form.rb b/app/forms/journeys/additional_payments_for_teaching/reminders/email_verification_form.rb deleted file mode 100644 index 098d921de8..0000000000 --- a/app/forms/journeys/additional_payments_for_teaching/reminders/email_verification_form.rb +++ /dev/null @@ -1,67 +0,0 @@ -module Journeys - module AdditionalPaymentsForTeaching - module Reminders - class EmailVerificationForm < Form - attribute :one_time_password - attribute :sent_one_time_password_at - - # Required for shared partial in the view - delegate :email_address, to: :answers - - validate :sent_one_time_password_must_be_valid - validate :otp_must_be_valid, if: :sent_one_time_password_at? - - def self.model_name - ActiveModel::Name.new(Form) - end - - before_validation do - self.one_time_password = one_time_password.gsub(/\D/, "") - end - - attr_reader :reminder - - def initialize(reminder:, journey_session:, journey:, params:) - @reminder = reminder - super(journey_session:, journey:, params:) - - assign_attributes(attributes_with_current_value) - end - - def save - return false unless valid? - - reminder.update!(email_verified: true) - end - - private - - def sent_one_time_password_must_be_valid - return if sent_one_time_password_at? - - errors.add(:one_time_password, i18n_errors_path(:"one_time_password.invalid")) - end - - def otp_must_be_valid - otp = OneTimePassword::Validator.new( - one_time_password, - sent_one_time_password_at, - secret: journey_session.answers.email_verification_secret - ) - - errors.add(:one_time_password, otp.warning) unless otp.valid? - end - - def sent_one_time_password_at? - sent_one_time_password_at&.to_datetime || false - rescue Date::Error - false - end - - def load_current_value(attribute) - reminder.public_send(attribute) if reminder.has_attribute?(attribute) - end - end - end - end -end diff --git a/app/forms/journeys/additional_payments_for_teaching/reminders/personal_details_form.rb b/app/forms/journeys/additional_payments_for_teaching/reminders/personal_details_form.rb deleted file mode 100644 index 5addd759af..0000000000 --- a/app/forms/journeys/additional_payments_for_teaching/reminders/personal_details_form.rb +++ /dev/null @@ -1,46 +0,0 @@ -module Journeys - module AdditionalPaymentsForTeaching - module Reminders - class PersonalDetailsForm < Form - attribute :full_name - attribute :email_address - - validates :full_name, presence: {message: i18n_error_message(:"full_name.blank")} - validates :full_name, length: {maximum: 100, message: i18n_error_message(:"full_name.length")} - - validates :email_address, presence: {message: i18n_error_message(:"email_address.blank")} - validates :email_address, format: {with: Rails.application.config.email_regexp, message: i18n_error_message(:"email_address.invalid")}, - length: {maximum: 256, message: i18n_error_message(:"email_address.length")}, if: -> { email_address.present? } - - def self.model_name - ActiveModel::Name.new(Form) - end - - attr_reader :reminder - - def initialize(reminder:, journey_session:, journey:, params:) - @reminder = reminder - super(journey_session:, journey:, params:) - - assign_attributes(attributes_with_current_value) - end - - def save - return false unless valid? - - reminder.update!(attributes) - end - - private - - def i18n_form_namespace - "reminders.#{super}" - end - - def load_current_value(attribute) - reminder.public_send(attribute) if reminder.has_attribute?(attribute) - end - end - end - end -end diff --git a/app/forms/reminders/confirmation_form.rb b/app/forms/reminders/confirmation_form.rb index 7c24e119aa..10c2f17c55 100644 --- a/app/forms/reminders/confirmation_form.rb +++ b/app/forms/reminders/confirmation_form.rb @@ -1,18 +1,44 @@ module Reminders class ConfirmationForm < Form def reminder - @reminder ||= Reminder.find_by( - full_name: journey_session.answers.reminder_full_name, - email_address: journey_session.answers.reminder_email_address, - email_verified: true, - itt_academic_year: next_academic_year.to_s - ) + @reminder ||= if submitted_claim + Reminder.find_by( + full_name: submitted_claim.full_name, + email_address: submitted_claim.email_address, + email_verified: true, + itt_subject: itt_subject_for_submitted_claim, + itt_academic_year: next_academic_year.to_s + ) + else + Reminder.find_by( + full_name: journey_session.answers.reminder_full_name, + email_address: journey_session.answers.reminder_email_address, + email_verified: true, + itt_subject:, + itt_academic_year: next_academic_year.to_s + ) + end + end + + def set_reminder_from_claim end private + def itt_subject + journey_session.answers.eligible_itt_subject + end + + def itt_subject_for_submitted_claim + submitted_claim.eligible_itt_subject + end + + def submitted_claim + Claim.find_by(id: session["submitted_claim_id"]) + end + def next_academic_year - AcademicYear.next + journey.configuration.current_academic_year + 1 end end end diff --git a/app/forms/reminders/email_verification_form.rb b/app/forms/reminders/email_verification_form.rb index a95bc6ae2b..1e6be2bc80 100644 --- a/app/forms/reminders/email_verification_form.rb +++ b/app/forms/reminders/email_verification_form.rb @@ -4,6 +4,10 @@ class EmailVerificationForm < Form validate :validate_otp_correct + def reminder_email_address + journey_session.answers.reminder_email_address + end + def save! return false if invalid? @@ -16,16 +20,24 @@ def save! full_name: journey_session.answers.reminder_full_name, email_address: journey_session.answers.reminder_email_address, email_verified: true, - itt_academic_year: next_academic_year.to_s + itt_academic_year: next_academic_year.to_s, + itt_subject: ) ReminderMailer.reminder_set(reminder).deliver_now end + def set_reminder_from_claim + end + private + def itt_subject + journey_session.answers.eligible_itt_subject + end + def next_academic_year - AcademicYear.next + journey.configuration.current_academic_year + 1 end def validate_otp_correct diff --git a/app/forms/reminders/personal_details_form.rb b/app/forms/reminders/personal_details_form.rb index 51c2296298..34963b0680 100644 --- a/app/forms/reminders/personal_details_form.rb +++ b/app/forms/reminders/personal_details_form.rb @@ -42,8 +42,36 @@ def save! journey_session.save! end + def set_reminder_from_claim + if submitted_claim.present? && submitted_claim.email_verified? + reminder = Reminder.find_or_create_by( + full_name: submitted_claim.full_name, + email_address: submitted_claim.email_address, + email_verified: true, + itt_subject: itt_subject_for_submitted_claim, + itt_academic_year: next_academic_year.to_s + ) + + ReminderMailer.reminder_set(reminder).deliver_now + else + false + end + end + private + def submitted_claim + Claim.find_by(id: session["submitted_claim_id"]) + end + + def itt_subject_for_submitted_claim + submitted_claim.eligible_itt_subject + end + + def next_academic_year + journey.configuration.current_academic_year + 1 + end + def reminder @reminder ||= Reminder.new( full_name: reminder_full_name, diff --git a/app/models/journeys/additional_payments_for_teaching.rb b/app/models/journeys/additional_payments_for_teaching.rb index 14cbaa4a3f..83c2dbafb6 100644 --- a/app/models/journeys/additional_payments_for_teaching.rb +++ b/app/models/journeys/additional_payments_for_teaching.rb @@ -27,10 +27,6 @@ module AdditionalPaymentsForTeaching "correct-school" => CorrectSchoolForm, "reset-claim" => ResetClaimForm, "select-home-address" => SelectHomeAddressForm - }, - "reminders" => { - "personal-details" => Reminders::PersonalDetailsForm, - "email-verification" => Reminders::EmailVerificationForm } }.freeze diff --git a/app/models/journeys/further_education_payments/session_answers.rb b/app/models/journeys/further_education_payments/session_answers.rb index c89fcae1aa..2a5e2779d0 100644 --- a/app/models/journeys/further_education_payments/session_answers.rb +++ b/app/models/journeys/further_education_payments/session_answers.rb @@ -26,12 +26,6 @@ class SessionAnswers < Journeys::SessionAnswers attribute :half_teaching_hours, :boolean attribute :award_amount, :decimal - # TODO: extract - attribute :reminder_full_name, :string - attribute :reminder_email_address, :string - attribute :reminder_otp_secret, :string - attribute :reminder_otp_confirmed, :boolean, default: false # whether or not they have confirmed email via otp - def policy Policies::FurtherEducationPayments end diff --git a/app/models/journeys/session_answers.rb b/app/models/journeys/session_answers.rb index 8d5afb0228..c1d973c93d 100644 --- a/app/models/journeys/session_answers.rb +++ b/app/models/journeys/session_answers.rb @@ -59,6 +59,11 @@ class SessionAnswers attribute :hmrc_validation_attempt_count, :integer attribute :reminder_id, :string + attribute :reminder_full_name, :string + attribute :reminder_email_address, :string + attribute :reminder_otp_secret, :string + attribute :reminder_otp_confirmed, :boolean, default: false # whether or not they have confirmed email via otp + def has_attribute?(name) attribute_names.include?(name.to_s) end diff --git a/app/models/policies/further_education_payments/eligibility.rb b/app/models/policies/further_education_payments/eligibility.rb index 231f27375b..33375244af 100644 --- a/app/models/policies/further_education_payments/eligibility.rb +++ b/app/models/policies/further_education_payments/eligibility.rb @@ -90,6 +90,10 @@ def provider_email verification.dig("verifier", "email") end + def eligible_itt_subject + nil + end + private def provider_and_claimant_names_match? diff --git a/app/views/additional_payments/claims/eligible_later.html.erb b/app/views/additional_payments/claims/eligible_later.html.erb index 05d00c1ca9..e85d0f1542 100644 --- a/app/views/additional_payments/claims/eligible_later.html.erb +++ b/app/views/additional_payments/claims/eligible_later.html.erb @@ -61,6 +61,6 @@ Receive a reminder email so you know when to apply. We cannot issue payments unless you apply.
- <%= link_to "Set reminder", new_reminder_path, class: "govuk-button", role: :button, data: { module: "govuk-button"} %> + <%= link_to "Set reminder", independent_reminder_path(journey: journey::ROUTING_NAME, slug: "personal-details"), class: "govuk-button", role: :button, data: { module: "govuk-button"} %> diff --git a/app/views/additional_payments/claims/future_eligibility.html.erb b/app/views/additional_payments/claims/future_eligibility.html.erb index 791614f671..da07573556 100644 --- a/app/views/additional_payments/claims/future_eligibility.html.erb +++ b/app/views/additional_payments/claims/future_eligibility.html.erb @@ -18,6 +18,6 @@ Receive a reminder email so you know when to check your eligibility and apply. We cannot issue payments unless you apply. - <%= link_to "Set reminder", new_reminder_path, class: "govuk-button", role: :button, data: { module: "govuk-button"} %> + <%= link_to "Set reminder", independent_reminder_path(journey: journey::ROUTING_NAME, slug: "personal-details"), class: "govuk-button", role: :button, data: { module: "govuk-button"} %> diff --git a/app/views/additional_payments/reminders/_one_time_password.html.erb b/app/views/additional_payments/reminders/_one_time_password.html.erb deleted file mode 100644 index 46481dbf21..0000000000 --- a/app/views/additional_payments/reminders/_one_time_password.html.erb +++ /dev/null @@ -1,36 +0,0 @@ -- <%= t("one_time_password.hint1_html", email_or_mobile_message: "an email", email_or_mobile_value: @form.email_address) %> -
- -- <%= t("one_time_password.validity_duration", duration_valid: one_time_password_validity_duration) %> -
- <% end %> - -- Tell us the email you want us to send reminders to. - We recommend you use a non-work email address in case your circumstances change. -
- -- To verify your email address we will send you an email with a 6-digit passcode. - You can enter the passcode on the next screen. -
- <% end %> - - <%= govuk_details(summary_text: "Get help with access codes") do %> -- If you have any issues with the passcode, email us at: - <%= govuk_mail_to support_email_address, support_email_address -%>. -
- <% end %> - - <%= f.govuk_submit "Continue" %> - <% end %> -- We will send you a verification email now. If you don’t receive one, - contact us on <%= mail_to t("support_email_address"), t("support_email_address"), class: "govuk-link" %>. -
- -- We will send you a reminder by email in September <%= current_reminder.send_year -%>. You will be able to check your eligibility and apply at this time. -
- -- Each application window will be open for 6 months from September in the year stated. If any of your employment circumstances change it might affect your eligibility. -
- -- It is your responsibility to apply for each payment you are eligible for. The Department for Education will not - issue payments unless you apply, also we will not issue payments for claims made after the window has closed. -
- -- <%= link_to "What do you think of this service?", done_page_url, class: "govuk-link" %> - (takes 30 seconds) -
-