add joined_at to memberships and phantoms for historical data
- editable field separate from created_at - active_during scope uses joined_at for filtering - backfills from created_at in migration
This commit is contained in:
parent
50e2318f59
commit
5968ed74d5
5 changed files with 58 additions and 4 deletions
|
|
@ -3,10 +3,10 @@
|
|||
module Api
|
||||
module V1
|
||||
class CrewMembershipBlueprint < ApiBlueprint
|
||||
fields :role, :retired, :retired_at, :created_at
|
||||
fields :role, :retired, :retired_at, :joined_at, :created_at
|
||||
|
||||
view :with_user do
|
||||
fields :role, :retired, :retired_at, :created_at
|
||||
fields :role, :retired, :retired_at, :joined_at, :created_at
|
||||
|
||||
field :user do |membership|
|
||||
UserBlueprint.render_as_hash(membership.user, view: :minimal)
|
||||
|
|
@ -14,7 +14,7 @@ module Api
|
|||
end
|
||||
|
||||
view :with_crew do
|
||||
fields :role, :retired, :retired_at, :created_at
|
||||
fields :role, :retired, :retired_at, :joined_at, :created_at
|
||||
|
||||
field :crew do |membership|
|
||||
CrewBlueprint.render_as_hash(membership.crew, view: :minimal)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
module Api
|
||||
module V1
|
||||
class PhantomPlayerBlueprint < ApiBlueprint
|
||||
fields :name, :granblue_id, :notes, :claim_confirmed
|
||||
fields :name, :granblue_id, :notes, :claim_confirmed, :retired, :retired_at, :joined_at
|
||||
|
||||
field :claimed do |phantom|
|
||||
phantom.claimed_by_id.present?
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ class CrewMembership < ApplicationRecord
|
|||
|
||||
enum :role, { member: 0, vice_captain: 1, captain: 2 }
|
||||
|
||||
before_validation :set_joined_at, on: :create
|
||||
|
||||
validates :user_id, uniqueness: { scope: :crew_id }
|
||||
validate :one_active_crew_per_user, on: :create
|
||||
validate :captain_limit
|
||||
|
|
@ -14,6 +16,13 @@ class CrewMembership < ApplicationRecord
|
|||
scope :active, -> { where(retired: false) }
|
||||
scope :retired, -> { where(retired: true) }
|
||||
|
||||
# Members who were active during a date range (either still active, or retired after the end date)
|
||||
# Uses joined_at (editable) instead of created_at (system timestamp) for historical accuracy
|
||||
scope :active_during, ->(start_date, end_date) {
|
||||
where('retired = false OR retired_at >= ?', start_date)
|
||||
.where('joined_at <= ?', end_date)
|
||||
}
|
||||
|
||||
def retire!
|
||||
update!(retired: true, retired_at: Time.current, role: :member)
|
||||
end
|
||||
|
|
@ -24,6 +33,10 @@ class CrewMembership < ApplicationRecord
|
|||
|
||||
private
|
||||
|
||||
def set_joined_at
|
||||
self.joined_at ||= Time.current
|
||||
end
|
||||
|
||||
def one_active_crew_per_user
|
||||
return if retired
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ class PhantomPlayer < ApplicationRecord
|
|||
|
||||
has_many :gw_individual_scores, dependent: :nullify
|
||||
|
||||
before_validation :set_joined_at, on: :create
|
||||
|
||||
validates :name, presence: true, length: { maximum: 100 }
|
||||
validates :granblue_id, length: { maximum: 20 }, allow_blank: true
|
||||
validates :granblue_id, uniqueness: { scope: :crew_id }, if: -> { granblue_id.present? }
|
||||
|
|
@ -17,6 +19,15 @@ class PhantomPlayer < ApplicationRecord
|
|||
scope :unclaimed, -> { where(claimed_by_id: nil) }
|
||||
scope :claimed, -> { where.not(claimed_by_id: nil) }
|
||||
scope :pending_confirmation, -> { claimed.where(claim_confirmed: false) }
|
||||
scope :active, -> { where(retired: false) }
|
||||
scope :retired, -> { where(retired: true) }
|
||||
|
||||
# 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
|
||||
scope :active_during, ->(start_date, end_date) {
|
||||
where('retired = false OR retired_at >= ?', start_date)
|
||||
.where('joined_at <= ?', end_date)
|
||||
}
|
||||
|
||||
# Assign this phantom to a user (officer action)
|
||||
def assign_to(user)
|
||||
|
|
@ -43,8 +54,17 @@ class PhantomPlayer < ApplicationRecord
|
|||
save!
|
||||
end
|
||||
|
||||
# Retire the phantom player (keeps scores)
|
||||
def retire!
|
||||
update!(retired: true, retired_at: Time.current)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_joined_at
|
||||
self.joined_at ||= Time.current
|
||||
end
|
||||
|
||||
def claimed_by_must_be_crew_member
|
||||
return unless claimed_by.present?
|
||||
return if claimed_by.crew == crew
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddJoinedAtToCrewMembershipsAndPhantomPlayers < ActiveRecord::Migration[8.0]
|
||||
def up
|
||||
add_column :crew_memberships, :joined_at, :datetime
|
||||
add_column :phantom_players, :joined_at, :datetime
|
||||
|
||||
# Backfill joined_at from created_at for existing records
|
||||
execute <<-SQL
|
||||
UPDATE crew_memberships SET joined_at = created_at WHERE joined_at IS NULL
|
||||
SQL
|
||||
execute <<-SQL
|
||||
UPDATE phantom_players SET joined_at = created_at WHERE joined_at IS NULL
|
||||
SQL
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :crew_memberships, :joined_at
|
||||
remove_column :phantom_players, :joined_at
|
||||
end
|
||||
end
|
||||
Loading…
Reference in a new issue