File size: 8,650 Bytes
f18c71f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
501d1e3
f18c71f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
501d1e3
f18c71f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
package controllers

import (
	"strconv"

	"abdanhafidz.com/go-boilerplate/services"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

type AdminStatisticController interface {
	GetSummary(ctx *gin.Context)
	GetMonthlyGrowth(ctx *gin.Context)
	GetEventOverview(ctx *gin.Context)
	GetEventDetail(ctx *gin.Context)
	GetExamOverview(ctx *gin.Context)
	GetExamDetail(ctx *gin.Context)
	GetAcademyOverview(ctx *gin.Context)
	GetAcademyDetail(ctx *gin.Context)
	GetProblemSetOverview(ctx *gin.Context)
	GetProblemSetDetail(ctx *gin.Context)
	GetQuestionOverview(ctx *gin.Context)
	GetQuestionDetail(ctx *gin.Context)
}

type adminStatisticController struct {
	adminStatisticService services.AdminStatisticService
}

func NewAdminStatisticController(adminStatisticService services.AdminStatisticService) AdminStatisticController {
	return &adminStatisticController{adminStatisticService: adminStatisticService}
}

// GetSummary godoc
// @Summary      Admin: Get Statistics Summary
// @Description  Retrieve aggregate statistics for dashboard cards such as users, academies, events, exams, problemsets, attempts, and payment metrics
// @Tags         AdminStatistic
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Success      200  {object}  dto.AdminStatisticSummaryResponse
// @Failure      401  {object}  dto.ErrorResponse
// @Failure      403  {object}  dto.ErrorResponse
// @Failure      500  {object}  dto.ErrorResponse
// @Router       /api/v1/admin/statistics/summary [get]
func (c *adminStatisticController) GetSummary(ctx *gin.Context) {
	summary, err := c.adminStatisticService.GetSummary(ctx.Request.Context())
	ResponseJSON(ctx, gin.H{}, summary, err)
}

// GetMonthlyGrowth godoc
// @Summary      Admin: Get Monthly Growth Statistics
// @Description  Retrieve monthly growth trend for users, academies, events, exams, and problemsets
// @Tags         AdminStatistic
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        months  query     int  false  "How many months to include"  default(6)
// @Success      200     {object}  dto.AdminStatisticMonthlyGrowthResponse
// @Failure      401     {object}  dto.ErrorResponse
// @Failure      403     {object}  dto.ErrorResponse
// @Failure      500     {object}  dto.ErrorResponse
// @Router       /api/v1/admin/statistics/monthly-growth [get]
func (c *adminStatisticController) GetMonthlyGrowth(ctx *gin.Context) {
	months, _ := strconv.Atoi(ctx.DefaultQuery("months", "6"))
	if months < 1 {
		months = 6
	}
	if months > 24 {
		months = 24
	}

	result, err := c.adminStatisticService.GetMonthlyGrowth(ctx.Request.Context(), months)
	meta := gin.H{"months": months}
	ResponseJSON(ctx, meta, result, err)
}

// GetEventOverview godoc
// @Summary      Admin: Get Event Statistics Overview
// @Description  Aggregate statistics for all events
// @Tags         AdminStatistic
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Router       /api/v1/admin/statistics/event [get]
func (c *adminStatisticController) GetEventOverview(ctx *gin.Context) {
	result, err := c.adminStatisticService.GetEventOverview(ctx.Request.Context())
	ResponseJSON(ctx, gin.H{}, result, err)
}

// GetEventDetail godoc
// @Summary      Admin: Get Event Statistics Detail
// @Description  Aggregate statistics for a single event
// @Tags         AdminStatistic
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        event_id  path     string  true  "Event ID"
// @Router       /api/v1/admin/statistics/event/{event_id} [get]
func (c *adminStatisticController) GetEventDetail(ctx *gin.Context) {
	eventID := ParseUUID(ctx, "event_id")
	if eventID == uuid.Nil {
		return
	}
	result, err := c.adminStatisticService.GetEventDetail(ctx.Request.Context(), eventID)
	ResponseJSON(ctx, gin.H{"event_id": eventID}, result, err)
}

// GetExamOverview godoc
// @Summary      Admin: Get Exam Statistics Overview
// @Description  Aggregate statistics for all exams
// @Tags         AdminStatistic
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Router       /api/v1/admin/statistics/exam [get]
func (c *adminStatisticController) GetExamOverview(ctx *gin.Context) {
	result, err := c.adminStatisticService.GetExamOverview(ctx.Request.Context())
	ResponseJSON(ctx, gin.H{}, result, err)
}

// GetExamDetail godoc
// @Summary      Admin: Get Exam Statistics Detail
// @Description  Aggregate statistics for a single exam
// @Tags         AdminStatistic
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        exam_id  path     string  true  "Exam ID"
// @Router       /api/v1/admin/statistics/exam/{exam_id} [get]
func (c *adminStatisticController) GetExamDetail(ctx *gin.Context) {
	examID := ParseUUID(ctx, "exam_id")
	if examID == uuid.Nil {
		return
	}
	result, err := c.adminStatisticService.GetExamDetail(ctx.Request.Context(), examID)
	ResponseJSON(ctx, gin.H{"exam_id": examID}, result, err)
}

// GetAcademyOverview godoc
// @Summary      Admin: Get Academy Statistics Overview
// @Description  Aggregate statistics for all academies
// @Tags         AdminStatistic
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Router       /api/v1/admin/statistics/academy [get]
func (c *adminStatisticController) GetAcademyOverview(ctx *gin.Context) {
	result, err := c.adminStatisticService.GetAcademyOverview(ctx.Request.Context())
	ResponseJSON(ctx, gin.H{}, result, err)
}

// GetAcademyDetail godoc
// @Summary      Admin: Get Academy Statistics Detail
// @Description  Aggregate statistics for a single academy
// @Tags         AdminStatistic
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        academy_id  path     string  true  "Academy ID"
// @Router       /api/v1/admin/statistics/academy/{academy_id} [get]
func (c *adminStatisticController) GetAcademyDetail(ctx *gin.Context) {
	academyID := ParseUUID(ctx, "academy_id")
	if academyID == uuid.Nil {
		return
	}
	result, err := c.adminStatisticService.GetAcademyDetail(ctx.Request.Context(), academyID)
	ResponseJSON(ctx, gin.H{"academy_id": academyID}, result, err)
}

// GetProblemSetOverview godoc
// @Summary      Admin: Get ProblemSet Statistics Overview
// @Description  Aggregate statistics for all problemsets
// @Tags         AdminStatistic
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Router       /api/v1/admin/statistics/problemset [get]
func (c *adminStatisticController) GetProblemSetOverview(ctx *gin.Context) {
	result, err := c.adminStatisticService.GetProblemSetOverview(ctx.Request.Context())
	ResponseJSON(ctx, gin.H{}, result, err)
}

// GetProblemSetDetail godoc
// @Summary      Admin: Get ProblemSet Statistics Detail
// @Description  Aggregate statistics for a single problemset
// @Tags         AdminStatistic
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        problemset_id  path     string  true  "ProblemSet ID"
// @Router       /api/v1/admin/statistics/problemset/{problemset_id} [get]
func (c *adminStatisticController) GetProblemSetDetail(ctx *gin.Context) {
	problemSetID := ParseUUID(ctx, "problemset_id")
	if problemSetID == uuid.Nil {
		return
	}
	result, err := c.adminStatisticService.GetProblemSetDetail(ctx.Request.Context(), problemSetID)
	ResponseJSON(ctx, gin.H{"problemset_id": problemSetID}, result, err)
}

// GetQuestionOverview godoc
// @Summary      Admin: Get Question Statistics Overview
// @Description  Aggregate statistics for all questions
// @Tags         AdminStatistic
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Router       /api/v1/admin/statistics/question [get]
func (c *adminStatisticController) GetQuestionOverview(ctx *gin.Context) {
	result, err := c.adminStatisticService.GetQuestionOverview(ctx.Request.Context())
	ResponseJSON(ctx, gin.H{}, result, err)
}

// GetQuestionDetail godoc
// @Summary      Admin: Get Question Statistics Detail
// @Description  Aggregate statistics for a single question
// @Tags         AdminStatistic
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        question_id  path     string  true  "Question ID"
// @Router       /api/v1/admin/statistics/question/{question_id} [get]
func (c *adminStatisticController) GetQuestionDetail(ctx *gin.Context) {
	questionID := ParseUUID(ctx, "question_id")
	if questionID == uuid.Nil {
		return
	}
	result, err := c.adminStatisticService.GetQuestionDetail(ctx.Request.Context(), questionID)
	ResponseJSON(ctx, gin.H{"question_id": questionID}, result, err)
}