diff --git a/app/controllers/api/v1/gw_individual_scores_controller.rb b/app/controllers/api/v1/gw_individual_scores_controller.rb index d46e88f..bd335fe 100644 --- a/app/controllers/api/v1/gw_individual_scores_controller.rb +++ b/app/controllers/api/v1/gw_individual_scores_controller.rb @@ -8,7 +8,8 @@ module Api before_action :restrict_access before_action :set_crew before_action :authorize_crew_member! - before_action :set_participation + before_action :set_participation, except: %i[create_by_event batch_by_event] + before_action :set_or_create_participation_by_event, only: %i[create_by_event batch_by_event] before_action :set_score, only: %i[update destroy] # POST /crew/gw_participations/:gw_participation_id/individual_scores @@ -56,6 +57,68 @@ module Api def batch return render_unauthorized_response unless current_user.crew_officer? + process_batch_scores + end + + # POST /crew/gw_events/:gw_event_id/individual_scores + # Auto-creates participation if needed, officers only + def create_by_event + return render_unauthorized_response unless current_user.crew_officer? + + score = @participation.gw_individual_scores.build(score_params_with_player) + score.recorded_by = current_user + + if score.save + render json: GwIndividualScoreBlueprint.render(score, view: :with_member, root: :individual_score), status: :created + else + render_validation_error_response(score) + end + end + + # POST /crew/gw_events/:gw_event_id/individual_scores/batch + # Auto-creates participation if needed, officers only + def batch_by_event + return render_unauthorized_response unless current_user.crew_officer? + + process_batch_scores + end + + private + + def set_crew + @crew = current_user.crew + raise CrewErrors::NotInCrewError unless @crew + end + + def set_participation + @participation = @crew.crew_gw_participations.find(params[:gw_participation_id]) + end + + def set_or_create_participation_by_event + event = GwEvent.find(params[:gw_event_id]) + @participation = @crew.crew_gw_participations.find_or_create_by!(gw_event: event) + end + + def set_score + @score = @participation.gw_individual_scores.find(params[:id]) + end + + def score_params + params.require(:individual_score).permit(:crew_membership_id, :round, :score, :is_cumulative) + end + + def score_params_with_player + params.require(:individual_score).permit(:crew_membership_id, :phantom_player_id, :round, :score, :is_cumulative) + end + + def can_record_score_for?(membership_id) + return true if current_user.crew_officer? + + # Regular members can only record their own scores + current_user.active_crew_membership&.id == membership_id + end + + def process_batch_scores scores_params = params.require(:scores) results = [] errors = [] @@ -63,6 +126,7 @@ module Api scores_params.each_with_index do |score_data, index| score = @participation.gw_individual_scores.find_or_initialize_by( crew_membership_id: score_data[:crew_membership_id], + phantom_player_id: score_data[:phantom_player_id], round: score_data[:round] ) score.assign_attributes( @@ -85,32 +149,6 @@ module Api status: :multi_status end end - - private - - def set_crew - @crew = current_user.crew - raise CrewErrors::NotInCrewError unless @crew - end - - def set_participation - @participation = @crew.crew_gw_participations.find(params[:gw_participation_id]) - end - - def set_score - @score = @participation.gw_individual_scores.find(params[:id]) - end - - def score_params - params.require(:individual_score).permit(:crew_membership_id, :round, :score, :is_cumulative) - end - - def can_record_score_for?(membership_id) - return true if current_user.crew_officer? - - # Regular members can only record their own scores - current_user.active_crew_membership&.id == membership_id - end end end end diff --git a/config/routes.rb b/config/routes.rb index 6dbf4a4..5d6aedb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -217,6 +217,11 @@ Rails.application.routes.draw do end end end + get 'gw_participations/by_event/:event_id', to: 'crew_gw_participations#by_event', as: :gw_participation_by_event + + # 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/batch', to: 'gw_individual_scores#batch_by_event' end # Reading collections - works for any user with privacy check