-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtraining_plan_proposals_controller.rb
More file actions
121 lines (95 loc) · 4.46 KB
/
Copy pathtraining_plan_proposals_controller.rb
File metadata and controls
121 lines (95 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# Правки плана тренировки: предлагает участник, судьбу решает организатор, а
# при голосовании — состав игры.
class TrainingPlanProposalsController < ApplicationController
before_action :set_game
before_action :set_proposal, except: :create
before_action :authorize_team_member!, only: :create
before_action :authorize_game_manager!, only: %i[update approve reject]
def create
@proposal = @game.training_plan_proposals.new(proposal_attributes.merge(user: current_user))
if @proposal.save
# Организатору спрашивать разрешения не у кого — его правка идёт сразу.
can_manage?(@game) ? approve_and_notify : TrainingPlanProposalNotifier.approval_requested(@proposal)
redirect_to @game, notice: t("games.training_plan_proposals.#{created_notice_key}")
else
redirect_to @game, alert: @proposal.errors.full_messages.to_sentence
end
end
# Организатор может поправить предложенное, прежде чем пускать его дальше.
def update
return redirect_to @game, alert: t("games.training_plan_proposals.closed") unless @proposal.pending?
if @proposal.update(proposal_attributes)
redirect_to @game, notice: t("games.training_plan_proposals.updated")
else
redirect_to @game, alert: @proposal.errors.full_messages.to_sentence
end
end
def approve
return redirect_to @game, alert: t("games.training_plan_proposals.closed") unless @proposal.pending?
approve_and_notify
redirect_to @game, notice: t("games.training_plan_proposals.#{@proposal.applied? ? "applied" : "vote_started"}")
end
def reject
return redirect_to @game, alert: t("games.training_plan_proposals.closed") unless @proposal.open?
@proposal.reject!
TrainingPlanProposalNotifier.settled(@proposal)
redirect_to @game, notice: t("games.training_plan_proposals.rejected")
end
def vote
unless @proposal.vote!(current_user, ActiveModel::Type::Boolean.new.cast(params[:in_favor]))
return redirect_to @game, alert: t("games.training_plan_proposals.vote_not_allowed")
end
TrainingPlanProposalNotifier.settled(@proposal) unless @proposal.open?
redirect_to @game, notice: t("games.training_plan_proposals.vote_counted")
end
# Автор забирает правку назад, организатор — убирает лишнее из списка.
def destroy
unless @proposal.user_id == current_user.id || can_manage?(@game)
return head :forbidden
end
@proposal.destroy
redirect_to @game, notice: t("games.training_plan_proposals.removed")
end
private
def set_game
@game = Game.find(params[:game_id])
end
def set_proposal
@proposal = @game.training_plan_proposals.find(params[:id])
end
def authorize_team_member!
head :forbidden unless team_member?
end
def authorize_game_manager!
head :forbidden unless can_manage?(@game)
end
def team_member?
current_user.admin? || @game.team_member_ids.include?(current_user.id)
end
def approve_and_notify
@proposal.approve!
if @proposal.voting?
TrainingPlanProposalNotifier.vote_started(@proposal)
else
TrainingPlanProposalNotifier.settled(@proposal)
end
end
def created_notice_key
return "created" unless can_manage?(@game)
@proposal.applied? ? "applied" : "vote_started"
end
def proposal_attributes
permitted = params.require(:training_plan_proposal).permit(:comment, :mode, training_block_ids: [])
permitted.to_h.merge("training_block_ids" => allowed_block_ids(permitted[:training_block_ids]))
end
# Блок из чужой библиотеки в план не попадает, даже если его id прислали в форме.
# Своё предложение — исключение: организатор правит его целиком, не теряя блок,
# который принёс из личной библиотеки автор правки.
def allowed_block_ids(ids)
ids = Array(ids).map(&:to_i).uniq.reject(&:zero?)
owner_ids = ([ current_user.id, @game.user_id ] + @game.assigned_coach_ids).compact.uniq
known_ids = @game.training_block_ids + Array(@proposal&.training_block_ids)
allowed = TrainingBlock.available_for(owner_ids, known_ids).where(id: ids).pluck(:id)
ids.select { |id| allowed.include?(id) }
end
end