1
1
package com .gdschongik .gdsc .domain .study .application ;
2
2
3
+ import static com .gdschongik .gdsc .domain .study .domain .AssignmentSubmissionStatus .SUCCESS ;
3
4
import static com .gdschongik .gdsc .global .exception .ErrorCode .*;
4
5
5
6
import com .gdschongik .gdsc .domain .member .domain .Member ;
7
+ import com .gdschongik .gdsc .domain .study .dao .AssignmentHistoryRepository ;
8
+ import com .gdschongik .gdsc .domain .study .dao .AttendanceRepository ;
6
9
import com .gdschongik .gdsc .domain .study .dao .StudyDetailRepository ;
10
+ import com .gdschongik .gdsc .domain .study .dao .StudyHistoryRepository ;
11
+ import com .gdschongik .gdsc .domain .study .dao .StudyRepository ;
12
+ import com .gdschongik .gdsc .domain .study .domain .Study ;
7
13
import com .gdschongik .gdsc .domain .study .domain .StudyDetail ;
8
14
import com .gdschongik .gdsc .domain .study .domain .StudyDetailValidator ;
15
+ import com .gdschongik .gdsc .domain .study .domain .StudyHistory ;
16
+ import com .gdschongik .gdsc .domain .study .domain .StudyValidator ;
9
17
import com .gdschongik .gdsc .domain .study .dto .request .AssignmentCreateUpdateRequest ;
10
18
import com .gdschongik .gdsc .domain .study .dto .response .AssignmentResponse ;
11
19
import com .gdschongik .gdsc .domain .study .dto .response .StudyCurriculumResponse ;
12
20
import com .gdschongik .gdsc .domain .study .dto .response .StudyMentorAttendanceResponse ;
21
+ import com .gdschongik .gdsc .domain .study .dto .response .StudyStatisticsResponse ;
22
+ import com .gdschongik .gdsc .domain .study .dto .response .StudyWeekStatisticsResponse ;
13
23
import com .gdschongik .gdsc .global .exception .CustomException ;
14
24
import com .gdschongik .gdsc .global .util .MemberUtil ;
15
25
import java .time .LocalDate ;
@@ -27,6 +37,11 @@ public class MentorStudyDetailService {
27
37
private final MemberUtil memberUtil ;
28
38
private final StudyDetailRepository studyDetailRepository ;
29
39
private final StudyDetailValidator studyDetailValidator ;
40
+ private final StudyHistoryRepository studyHistoryRepository ;
41
+ private final AttendanceRepository attendanceRepository ;
42
+ private final AssignmentHistoryRepository assignmentHistoryRepository ;
43
+ private final StudyValidator studyValidator ;
44
+ private final StudyRepository studyRepository ;
30
45
31
46
@ Transactional (readOnly = true )
32
47
public List <AssignmentResponse > getWeeklyAssignments (Long studyId ) {
@@ -108,4 +123,83 @@ public List<StudyMentorAttendanceResponse> getAttendanceNumbers(Long studyId) {
108
123
.limit (2 )
109
124
.toList ();
110
125
}
126
+
127
+ @ Transactional (readOnly = true )
128
+ public StudyStatisticsResponse getStudyStatistics (Long studyId ) {
129
+ Member currentMember = memberUtil .getCurrentMember ();
130
+ Study study = studyRepository .findById (studyId ).orElseThrow (() -> new CustomException (STUDY_NOT_FOUND ));
131
+ List <StudyHistory > studyHistories = studyHistoryRepository .findAllByStudyId (studyId );
132
+ List <StudyDetail > studyDetails = studyDetailRepository .findAllByStudyIdOrderByWeekAsc (studyId );
133
+ studyValidator .validateStudyMentor (currentMember , study );
134
+
135
+ long totalStudentCount = studyHistories .size ();
136
+ long studyCompletedStudentCount =
137
+ studyHistories .stream ().filter (StudyHistory ::isCompleted ).count ();
138
+
139
+ List <StudyWeekStatisticsResponse > studyWeekStatisticsResponses = studyDetails .stream ()
140
+ .map ((studyDetail -> calculateWeekStatistics (studyDetail , totalStudentCount )))
141
+ .toList ();
142
+
143
+ long averageAttendanceRate = calculateAverageWeekAttendanceRate (studyWeekStatisticsResponses );
144
+ long averageAssignmentSubmissionRate =
145
+ calculateAverageWeekAssignmentSubmissionRate (studyWeekStatisticsResponses );
146
+
147
+ return StudyStatisticsResponse .of (
148
+ totalStudentCount ,
149
+ studyCompletedStudentCount ,
150
+ averageAttendanceRate ,
151
+ averageAssignmentSubmissionRate ,
152
+ studyWeekStatisticsResponses );
153
+ }
154
+
155
+ private StudyWeekStatisticsResponse calculateWeekStatistics (StudyDetail studyDetail , Long totalStudentCount ) {
156
+ boolean isNotOpenedCurriculum = !studyDetail .getCurriculum ().isOpen ();
157
+ boolean isNotOpenedAssignment = !studyDetail .getAssignment ().isOpen () || isNotOpenedCurriculum ;
158
+
159
+ if (totalStudentCount == 0 ) {
160
+ return StudyWeekStatisticsResponse .empty (
161
+ studyDetail .getWeek (), isNotOpenedAssignment , isNotOpenedCurriculum );
162
+ }
163
+
164
+ if (isNotOpenedCurriculum ) {
165
+ return StudyWeekStatisticsResponse .canceledWeek (studyDetail .getWeek ());
166
+ }
167
+
168
+ long attendanceCount = attendanceRepository .countByStudyDetailId (studyDetail .getId ());
169
+ long attendanceRate = Math .round (attendanceCount / (double ) totalStudentCount * 100 );
170
+
171
+ if (isNotOpenedAssignment ) {
172
+ return StudyWeekStatisticsResponse .assignmentCanceled (studyDetail .getWeek (), attendanceRate );
173
+ }
174
+
175
+ long successfullySubmittedAssignmentCount =
176
+ assignmentHistoryRepository .countByStudyDetailIdAndSubmissionStatusEquals (studyDetail .getId (), SUCCESS );
177
+ long assignmentSubmissionRate =
178
+ Math .round (successfullySubmittedAssignmentCount / (double ) totalStudentCount * 100 );
179
+
180
+ return StudyWeekStatisticsResponse .opened (studyDetail .getWeek (), attendanceRate , assignmentSubmissionRate );
181
+ }
182
+
183
+ private long calculateAverageWeekAttendanceRate (List <StudyWeekStatisticsResponse > studyWeekStatisticsResponses ) {
184
+
185
+ double averageAttendanceRate = studyWeekStatisticsResponses .stream ()
186
+ .filter (weekStatisticsResponse -> !weekStatisticsResponse .isCurriculumCanceled ())
187
+ .mapToLong (StudyWeekStatisticsResponse ::attendanceRate )
188
+ .average ()
189
+ .orElse (0 );
190
+
191
+ return Math .round (averageAttendanceRate );
192
+ }
193
+
194
+ private long calculateAverageWeekAssignmentSubmissionRate (
195
+ List <StudyWeekStatisticsResponse > studyWeekStatisticsResponses ) {
196
+
197
+ double averageAssignmentSubmissionRate = studyWeekStatisticsResponses .stream ()
198
+ .filter (studyWeekStatistics -> !studyWeekStatistics .isAssignmentCanceled ())
199
+ .mapToLong (StudyWeekStatisticsResponse ::assignmentSubmissionRate )
200
+ .average ()
201
+ .orElse (0 );
202
+
203
+ return Math .round (averageAssignmentSubmissionRate );
204
+ }
111
205
}
0 commit comments