diff --git a/app/controllers/unsubscribe_controller.rb b/app/controllers/unsubscribe_controller.rb index b0f7ae2efc..bd2551e6e6 100644 --- a/app/controllers/unsubscribe_controller.rb +++ b/app/controllers/unsubscribe_controller.rb @@ -15,7 +15,7 @@ def create if @form.reminder.nil? head :bad_request else - @form.reminder.destroy + @form.reminder.soft_delete! end end diff --git a/app/forms/unsubscribe/confirmation_form.rb b/app/forms/unsubscribe/confirmation_form.rb index 726180ac3c..3ee53d7d46 100644 --- a/app/forms/unsubscribe/confirmation_form.rb +++ b/app/forms/unsubscribe/confirmation_form.rb @@ -6,7 +6,7 @@ class ConfirmationForm attribute :id, :string def reminder - @reminder ||= Reminder.find_by(id:) + @reminder ||= Reminder.not_deleted.find_by(id:) end def obfuscasted_email diff --git a/app/models/reminder.rb b/app/models/reminder.rb index 4f59c79262..835eae7dc3 100644 --- a/app/models/reminder.rb +++ b/app/models/reminder.rb @@ -7,6 +7,7 @@ class Reminder < ApplicationRecord scope :by_journey, ->(journey) { where(journey_class: journey.to_s) } scope :inside_academic_year, -> { where(itt_academic_year: AcademicYear.current.to_s) } scope :to_be_sent, -> { email_verified.not_yet_sent.inside_academic_year } + scope :not_deleted, -> { where(deleted_at: nil) } def journey journey_class.constantize @@ -21,4 +22,8 @@ def itt_academic_year read_attribute(:itt_academic_year) ) end + + def soft_delete! + update!(deleted_at: Time.now) + end end diff --git a/db/migrate/20241206105631_add_deleted_at_to_reminders.rb b/db/migrate/20241206105631_add_deleted_at_to_reminders.rb new file mode 100644 index 0000000000..ac3fdad0bc --- /dev/null +++ b/db/migrate/20241206105631_add_deleted_at_to_reminders.rb @@ -0,0 +1,5 @@ +class AddDeletedAtToReminders < ActiveRecord::Migration[7.2] + def change + add_column :reminders, :deleted_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index b321aed1e0..a5c6bb8c40 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.2].define(version: 2024_11_26_105650) do +ActiveRecord::Schema[7.2].define(version: 2024_12_06_105631) do # These are extensions that must be enabled in order to support this database enable_extension "citext" enable_extension "pg_trgm" @@ -428,6 +428,7 @@ t.string "itt_academic_year", limit: 9 t.string "itt_subject" t.text "journey_class", null: false + t.datetime "deleted_at" t.index ["journey_class"], name: "index_reminders_on_journey_class" end diff --git a/spec/factories/reminders.rb b/spec/factories/reminders.rb index fe72cc3990..5b143f6766 100644 --- a/spec/factories/reminders.rb +++ b/spec/factories/reminders.rb @@ -11,5 +11,9 @@ trait :with_fe_reminder do journey_class { Journeys::FurtherEducationPayments.to_s } end + + trait :soft_deleted do + deleted_at { 1.second.ago } + end end end diff --git a/spec/features/unsubscribe_spec.rb b/spec/features/unsubscribe_spec.rb index 7b7e742af6..5e3b0f7816 100644 --- a/spec/features/unsubscribe_spec.rb +++ b/spec/features/unsubscribe_spec.rb @@ -12,9 +12,9 @@ visit "/#{reminder.journey::ROUTING_NAME}/unsubscribe/reminders/#{reminder.id}" expect(page).to have_content "Are you sure you wish to unsub" - expect { - click_button("Unsubscribe") - }.to change(Reminder, :count).by(-1) + click_button("Unsubscribe") + + expect(reminder.reload.deleted_at).to be_present expect(page).to have_content "Unsubscribe complete" end @@ -23,4 +23,19 @@ visit "/#{reminder.journey::ROUTING_NAME}/unsubscribe/reminders/idonotexist" expect(page).to have_content "We can’t find your subscription" end + + context "when reminder already soft deleted" do + let(:reminder) do + create( + :reminder, + :soft_deleted, + journey_class: Journeys::FurtherEducationPayments.to_s + ) + end + + scenario "cannot find subscription" do + visit "/#{reminder.journey::ROUTING_NAME}/unsubscribe/reminders/#{reminder.id}" + expect(page).to have_content "We can’t find your subscription" + end + end end diff --git a/spec/requests/unsubscribe_spec.rb b/spec/requests/unsubscribe_spec.rb index 053e929d26..c58a25b02b 100644 --- a/spec/requests/unsubscribe_spec.rb +++ b/spec/requests/unsubscribe_spec.rb @@ -1,14 +1,14 @@ require "rails_helper" RSpec.describe "unsubscribe", type: :request do - let!(:reminder) { create(:reminder, :with_fe_reminder) } + let(:reminder) { create(:reminder, :with_fe_reminder) } describe "POST #create" do context "happy path" do - it "unsubscribes from reminder via one click unsubscribe" do - expect { - post "/further-education-payments/unsubscribe/reminders", params: {id: reminder.id} - }.to change(Reminder, :count).by(-1) + it "sets deleted_at from reminder via one click unsubscribe" do + post "/further-education-payments/unsubscribe/reminders", params: {id: reminder.id} + + expect(reminder.reload.deleted_at).to be_present expect(response).to be_successful end @@ -21,5 +21,15 @@ expect(response).to be_bad_request end end + + context "when already soft deleted" do + let(:reminder) { create(:reminder, :with_fe_reminder, :soft_deleted) } + + it "returns 400 error" do + post "/further-education-payments/unsubscribe/reminders", params: {id: reminder.id} + + expect(response).to be_bad_request + end + end end end