add gw scores history endpoints for members and phantoms
This commit is contained in:
parent
cc722b9660
commit
4a6ae93d20
4 changed files with 83 additions and 3 deletions
|
|
@ -6,11 +6,14 @@ module Api
|
||||||
include CrewAuthorizationConcern
|
include CrewAuthorizationConcern
|
||||||
|
|
||||||
before_action :restrict_access
|
before_action :restrict_access
|
||||||
before_action :set_crew
|
before_action :set_crew, except: %i[gw_scores]
|
||||||
|
before_action :set_crew_from_user, only: %i[gw_scores]
|
||||||
before_action :set_membership, only: %i[update destroy promote demote]
|
before_action :set_membership, only: %i[update destroy promote demote]
|
||||||
|
before_action :set_membership_for_scores, only: %i[gw_scores]
|
||||||
before_action :authorize_crew_officer!, only: %i[destroy]
|
before_action :authorize_crew_officer!, only: %i[destroy]
|
||||||
before_action :authorize_crew_captain!, only: %i[promote demote]
|
before_action :authorize_crew_captain!, only: %i[promote demote]
|
||||||
before_action :authorize_membership_update!, only: %i[update]
|
before_action :authorize_membership_update!, only: %i[update]
|
||||||
|
before_action :authorize_crew_member!, only: %i[gw_scores]
|
||||||
|
|
||||||
# PUT /crews/:crew_id/memberships/:id
|
# PUT /crews/:crew_id/memberships/:id
|
||||||
def update
|
def update
|
||||||
|
|
@ -55,16 +58,51 @@ module Api
|
||||||
render json: CrewMembershipBlueprint.render(@membership, view: :with_user, root: :membership)
|
render json: CrewMembershipBlueprint.render(@membership, view: :with_user, root: :membership)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# GET /crew/memberships/:id/gw_scores
|
||||||
|
def gw_scores
|
||||||
|
# Group scores by participation/event and calculate totals
|
||||||
|
scores_by_event = @membership.gw_individual_scores
|
||||||
|
.includes(crew_gw_participation: :gw_event)
|
||||||
|
.group_by(&:crew_gw_participation)
|
||||||
|
|
||||||
|
event_scores = scores_by_event.map do |participation, scores|
|
||||||
|
{
|
||||||
|
gw_event: GwEventBlueprint.render_as_hash(participation.gw_event),
|
||||||
|
total_score: scores.sum(&:score)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Sort by event number descending (most recent first)
|
||||||
|
event_scores.sort_by! { |es| -es[:gw_event][:event_number] }
|
||||||
|
|
||||||
|
grand_total = event_scores.sum { |es| es[:total_score] }
|
||||||
|
|
||||||
|
render json: {
|
||||||
|
member: CrewMembershipBlueprint.render_as_hash(@membership, view: :with_user),
|
||||||
|
event_scores: event_scores,
|
||||||
|
grand_total: grand_total
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_crew
|
def set_crew
|
||||||
@crew = Crew.find(params[:crew_id])
|
@crew = Crew.find(params[:crew_id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_crew_from_user
|
||||||
|
@crew = current_user.crew
|
||||||
|
raise CrewErrors::NotInCrewError unless @crew
|
||||||
|
end
|
||||||
|
|
||||||
def set_membership
|
def set_membership
|
||||||
@membership = @crew.crew_memberships.find(params[:id])
|
@membership = @crew.crew_memberships.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_membership_for_scores
|
||||||
|
@membership = @crew.crew_memberships.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
def membership_params
|
def membership_params
|
||||||
params.require(:membership).permit(:role, :joined_at, :retired, :retired_at)
|
params.require(:membership).permit(:role, :joined_at, :retired, :retired_at)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,12 @@ module Api
|
||||||
include CrewAuthorizationConcern
|
include CrewAuthorizationConcern
|
||||||
|
|
||||||
before_action :restrict_access
|
before_action :restrict_access
|
||||||
before_action :set_crew
|
before_action :set_crew, except: %i[gw_scores]
|
||||||
before_action :authorize_crew_member!, only: %i[index confirm_claim decline_claim]
|
before_action :set_crew_from_user, only: %i[gw_scores]
|
||||||
|
before_action :authorize_crew_member!, only: %i[index confirm_claim decline_claim gw_scores]
|
||||||
before_action :authorize_crew_officer!, only: %i[create bulk_create update destroy assign]
|
before_action :authorize_crew_officer!, only: %i[create bulk_create update destroy assign]
|
||||||
before_action :set_phantom, only: %i[show update destroy assign confirm_claim decline_claim]
|
before_action :set_phantom, only: %i[show update destroy assign confirm_claim decline_claim]
|
||||||
|
before_action :set_phantom_for_scores, only: %i[gw_scores]
|
||||||
|
|
||||||
# GET /crews/:crew_id/phantom_players
|
# GET /crews/:crew_id/phantom_players
|
||||||
def index
|
def index
|
||||||
|
|
@ -86,16 +88,51 @@ module Api
|
||||||
render json: PhantomPlayerBlueprint.render(@phantom, view: :with_claimed_by, root: :phantom_player)
|
render json: PhantomPlayerBlueprint.render(@phantom, view: :with_claimed_by, root: :phantom_player)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# GET /crew/phantom_players/:id/gw_scores
|
||||||
|
def gw_scores
|
||||||
|
# Group scores by participation/event and calculate totals
|
||||||
|
scores_by_event = @phantom.gw_individual_scores
|
||||||
|
.includes(crew_gw_participation: :gw_event)
|
||||||
|
.group_by(&:crew_gw_participation)
|
||||||
|
|
||||||
|
event_scores = scores_by_event.map do |participation, scores|
|
||||||
|
{
|
||||||
|
gw_event: GwEventBlueprint.render_as_hash(participation.gw_event),
|
||||||
|
total_score: scores.sum(&:score)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Sort by event number descending (most recent first)
|
||||||
|
event_scores.sort_by! { |es| -es[:gw_event][:event_number] }
|
||||||
|
|
||||||
|
grand_total = event_scores.sum { |es| es[:total_score] }
|
||||||
|
|
||||||
|
render json: {
|
||||||
|
phantom: PhantomPlayerBlueprint.render_as_hash(@phantom),
|
||||||
|
event_scores: event_scores,
|
||||||
|
grand_total: grand_total
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_crew
|
def set_crew
|
||||||
@crew = Crew.find(params[:crew_id])
|
@crew = Crew.find(params[:crew_id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_crew_from_user
|
||||||
|
@crew = current_user.crew
|
||||||
|
raise CrewErrors::NotInCrewError unless @crew
|
||||||
|
end
|
||||||
|
|
||||||
def set_phantom
|
def set_phantom
|
||||||
@phantom = @crew.phantom_players.find(params[:id])
|
@phantom = @crew.phantom_players.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_phantom_for_scores
|
||||||
|
@phantom = @crew.phantom_players.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
def phantom_params
|
def phantom_params
|
||||||
params.require(:phantom_player).permit(:name, :granblue_id, :notes, :joined_at, :retired, :retired_at)
|
params.require(:phantom_player).permit(:name, :granblue_id, :notes, :joined_at, :retired, :retired_at)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
class CrewMembership < ApplicationRecord
|
class CrewMembership < ApplicationRecord
|
||||||
belongs_to :crew
|
belongs_to :crew
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
|
has_many :gw_individual_scores, dependent: :nullify
|
||||||
|
|
||||||
enum :role, { member: 0, vice_captain: 1, captain: 2 }
|
enum :role, { member: 0, vice_captain: 1, captain: 2 }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -238,6 +238,10 @@ Rails.application.routes.draw do
|
||||||
# Create individual scores by event (auto-creates participation if needed)
|
# Create individual scores by event (auto-creates participation if needed)
|
||||||
post 'gw_events/:gw_event_id/individual_scores', to: 'gw_individual_scores#create_by_event'
|
post 'gw_events/:gw_event_id/individual_scores', to: 'gw_individual_scores#create_by_event'
|
||||||
post 'gw_events/:gw_event_id/individual_scores/batch', to: 'gw_individual_scores#batch_by_event'
|
post 'gw_events/:gw_event_id/individual_scores/batch', to: 'gw_individual_scores#batch_by_event'
|
||||||
|
|
||||||
|
# Member/phantom GW score history
|
||||||
|
get 'memberships/:id/gw_scores', to: 'crew_memberships#gw_scores'
|
||||||
|
get 'phantom_players/:id/gw_scores', to: 'phantom_players#gw_scores'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Reading collections - works for any user with privacy check
|
# Reading collections - works for any user with privacy check
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue