diff --git a/app/controllers/api/v1/crews_controller.rb b/app/controllers/api/v1/crews_controller.rb index 24a33f1..f0a2361 100644 --- a/app/controllers/api/v1/crews_controller.rb +++ b/app/controllers/api/v1/crews_controller.rb @@ -55,10 +55,10 @@ module Api phantoms = [] when :phantom members = [] - phantoms = @crew.phantom_players.includes(:claimed_by).order(:name) + phantoms = @crew.phantom_players.not_deleted.includes(:claimed_by).order(:name) when :all members = @crew.crew_memberships.includes(:user).order(role: :desc, retired: :asc, created_at: :asc) - phantoms = @crew.phantom_players.includes(:claimed_by).order(:name) + phantoms = @crew.phantom_players.not_deleted.includes(:claimed_by).order(:name) else members = @crew.active_memberships.includes(:user).order(role: :desc, created_at: :asc) phantoms = [] diff --git a/app/controllers/api/v1/phantom_claims_controller.rb b/app/controllers/api/v1/phantom_claims_controller.rb index 1e8320a..4c981a7 100644 --- a/app/controllers/api/v1/phantom_claims_controller.rb +++ b/app/controllers/api/v1/phantom_claims_controller.rb @@ -9,6 +9,7 @@ module Api # Returns phantom players assigned to the current user that are pending confirmation def index phantoms = PhantomPlayer + .not_deleted .includes(:crew, :claimed_by) .where(claimed_by: current_user, claim_confirmed: false) .order(created_at: :desc) diff --git a/app/controllers/api/v1/phantom_players_controller.rb b/app/controllers/api/v1/phantom_players_controller.rb index 323a1a4..d4b7907 100644 --- a/app/controllers/api/v1/phantom_players_controller.rb +++ b/app/controllers/api/v1/phantom_players_controller.rb @@ -13,7 +13,7 @@ module Api # GET /crews/:crew_id/phantom_players def index - phantoms = @crew.phantom_players.includes(:claimed_by).order(:name) + phantoms = @crew.phantom_players.not_deleted.includes(:claimed_by).order(:name) render json: PhantomPlayerBlueprint.render(phantoms, view: :with_claimed_by, root: :phantom_players) end diff --git a/app/models/phantom_player.rb b/app/models/phantom_player.rb index 6e681f1..2ad61c1 100644 --- a/app/models/phantom_player.rb +++ b/app/models/phantom_player.rb @@ -21,6 +21,8 @@ class PhantomPlayer < ApplicationRecord scope :pending_confirmation, -> { claimed.where(claim_confirmed: false) } scope :active, -> { where(retired: false) } scope :retired, -> { where(retired: true) } + scope :not_deleted, -> { where(deleted_at: nil) } + scope :deleted, -> { where.not(deleted_at: nil) } # Phantoms who were active during a date range (either still active, or retired after the end date) # Uses joined_at (editable) instead of created_at for historical accuracy @@ -39,12 +41,19 @@ class PhantomPlayer < ApplicationRecord end # Confirm the claim (user action) + # After confirmation, soft deletes the phantom since scores have been transferred def confirm_claim!(user) raise CrewErrors::NotClaimedByUserError unless claimed_by == user self.claim_confirmed = true transfer_scores_to_membership! save! + soft_delete! + end + + # Soft delete the phantom (keeps record for logging) + def soft_delete! + update!(deleted_at: Time.current) end # Unassign the phantom (officer action or user rejection) diff --git a/db/migrate/20251217195837_add_deleted_at_to_phantom_players.rb b/db/migrate/20251217195837_add_deleted_at_to_phantom_players.rb new file mode 100644 index 0000000..694bbac --- /dev/null +++ b/db/migrate/20251217195837_add_deleted_at_to_phantom_players.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +class AddDeletedAtToPhantomPlayers < ActiveRecord::Migration[8.0] + def change + add_column :phantom_players, :deleted_at, :datetime + add_index :phantom_players, :deleted_at + end +end diff --git a/db/schema.rb b/db/schema.rb index 0c9e66d..45e0ef2 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[8.0].define(version: 2025_12_15_173625) do +ActiveRecord::Schema[8.0].define(version: 2025_12_17_195837) do # These are extensions that must be enabled in order to support this database enable_extension "btree_gin" enable_extension "pg_catalog.plpgsql" @@ -688,10 +688,12 @@ ActiveRecord::Schema[8.0].define(version: 2025_12_15_173625) do t.boolean "retired", default: false, null: false t.datetime "retired_at" t.datetime "joined_at" + t.datetime "deleted_at" t.index ["claimed_by_id"], name: "index_phantom_players_on_claimed_by_id" t.index ["claimed_from_membership_id"], name: "index_phantom_players_on_claimed_from_membership_id" t.index ["crew_id", "granblue_id"], name: "index_phantom_players_on_crew_id_and_granblue_id", unique: true, where: "(granblue_id IS NOT NULL)" t.index ["crew_id"], name: "index_phantom_players_on_crew_id" + t.index ["deleted_at"], name: "index_phantom_players_on_deleted_at" end create_table "raid_groups", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|