soft delete phantoms after claim confirmation

keeps phantom records for logging, excludes from all queries
This commit is contained in:
Justin Edmund 2025-12-17 20:05:01 -08:00
parent de72d21e24
commit 5afd31fdb6
6 changed files with 24 additions and 4 deletions

View file

@ -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 = []

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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|