Skip to content

Commit dd03e40

Browse files
committed
feat: implement Team Goals controller with progress tracking
- Add full CRUD operations for team and player goals - Implement filtering by status, category, type, player - Calculate goal summaries and statistics - Add support for overdue and expiring goals - Include progress tracking and completion metrics
1 parent 4d0d957 commit dd03e40

1 file changed

Lines changed: 139 additions & 0 deletions

File tree

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
class Api::V1::TeamGoalsController < Api::V1::BaseController
2+
before_action :set_team_goal, only: [:show, :update, :destroy]
3+
4+
def index
5+
goals = organization_scoped(TeamGoal).includes(:player, :assigned_to, :created_by)
6+
7+
# Apply filters
8+
goals = goals.by_status(params[:status]) if params[:status].present?
9+
goals = goals.by_category(params[:category]) if params[:category].present?
10+
goals = goals.for_player(params[:player_id]) if params[:player_id].present?
11+
12+
# Special filters
13+
goals = goals.team_goals if params[:type] == 'team'
14+
goals = goals.player_goals if params[:type] == 'player'
15+
goals = goals.active if params[:active] == 'true'
16+
goals = goals.overdue if params[:overdue] == 'true'
17+
goals = goals.expiring_soon(params[:expiring_days]&.to_i || 7) if params[:expiring_soon] == 'true'
18+
19+
# Assigned to filter
20+
goals = goals.where(assigned_to_id: params[:assigned_to_id]) if params[:assigned_to_id].present?
21+
22+
# Sorting
23+
sort_by = params[:sort_by] || 'created_at'
24+
sort_order = params[:sort_order] || 'desc'
25+
goals = goals.order("#{sort_by} #{sort_order}")
26+
27+
# Pagination
28+
result = paginate(goals)
29+
30+
render_success({
31+
goals: TeamGoalSerializer.render_as_hash(result[:data]),
32+
pagination: result[:pagination],
33+
summary: calculate_goals_summary(goals)
34+
})
35+
end
36+
37+
def show
38+
render_success({
39+
goal: TeamGoalSerializer.render_as_hash(@goal)
40+
})
41+
end
42+
43+
def create
44+
goal = organization_scoped(TeamGoal).new(team_goal_params)
45+
goal.organization = current_organization
46+
goal.created_by = current_user
47+
48+
if goal.save
49+
log_user_action(
50+
action: 'create',
51+
entity_type: 'TeamGoal',
52+
entity_id: goal.id,
53+
new_values: goal.attributes
54+
)
55+
56+
render_created({
57+
goal: TeamGoalSerializer.render_as_hash(goal)
58+
}, message: 'Goal created successfully')
59+
else
60+
render_error(
61+
message: 'Failed to create goal',
62+
code: 'VALIDATION_ERROR',
63+
status: :unprocessable_entity,
64+
details: goal.errors.as_json
65+
)
66+
end
67+
end
68+
69+
def update
70+
old_values = @goal.attributes.dup
71+
72+
if @goal.update(team_goal_params)
73+
log_user_action(
74+
action: 'update',
75+
entity_type: 'TeamGoal',
76+
entity_id: @goal.id,
77+
old_values: old_values,
78+
new_values: @goal.attributes
79+
)
80+
81+
render_updated({
82+
goal: TeamGoalSerializer.render_as_hash(@goal)
83+
})
84+
else
85+
render_error(
86+
message: 'Failed to update goal',
87+
code: 'VALIDATION_ERROR',
88+
status: :unprocessable_entity,
89+
details: @goal.errors.as_json
90+
)
91+
end
92+
end
93+
94+
def destroy
95+
if @goal.destroy
96+
log_user_action(
97+
action: 'delete',
98+
entity_type: 'TeamGoal',
99+
entity_id: @goal.id,
100+
old_values: @goal.attributes
101+
)
102+
103+
render_deleted(message: 'Goal deleted successfully')
104+
else
105+
render_error(
106+
message: 'Failed to delete goal',
107+
code: 'DELETE_ERROR',
108+
status: :unprocessable_entity
109+
)
110+
end
111+
end
112+
113+
private
114+
115+
def set_team_goal
116+
@goal = organization_scoped(TeamGoal).find(params[:id])
117+
end
118+
119+
def team_goal_params
120+
params.require(:team_goal).permit(
121+
:title, :description, :category, :metric_type,
122+
:target_value, :current_value, :start_date, :end_date,
123+
:status, :progress, :notes,
124+
:player_id, :assigned_to_id
125+
)
126+
end
127+
128+
def calculate_goals_summary(goals)
129+
{
130+
total: goals.count,
131+
by_status: goals.group(:status).count,
132+
by_category: goals.group(:category).count,
133+
active_count: goals.active.count,
134+
completed_count: goals.where(status: 'completed').count,
135+
overdue_count: goals.overdue.count,
136+
avg_progress: goals.active.average(:progress)&.round(1) || 0
137+
}
138+
end
139+
end

0 commit comments

Comments
 (0)