Skip to content

Commit a999f9e

Browse files
committed
refactor: 성적 조회시 통계도 같이 조회되도록 수정
1 parent 0bcfdfb commit a999f9e

5 files changed

Lines changed: 145 additions & 51 deletions

File tree

Lines changed: 83 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,113 @@
11
package com.neeis.neeis.domain.score.dto.res;
22

3+
import io.swagger.v3.oas.annotations.media.Schema;
34
import lombok.Builder;
45
import lombok.Getter;
56

67
import java.util.List;
78

89
@Getter
910
public class ScoreSummaryBySubjectDto {
11+
12+
@Schema(description = "과목명", example = "독서와 문법")
1013
private final String subjectName;
11-
private final List<EvaluationMethodScoreDto> evaluations;
14+
15+
@Schema(description = "평가 항목 정보 (ID와 제목)")
16+
private final List<EvaluationDto> evaluations;
17+
18+
@Schema(description = "학생별 성적 정보")
19+
private final List<StudentScoreDto> students;
1220

1321
@Builder
14-
private ScoreSummaryBySubjectDto(String subjectName, List<EvaluationMethodScoreDto> evaluations) {
22+
private ScoreSummaryBySubjectDto(String subjectName, List<EvaluationDto> evaluations, List<StudentScoreDto> students) {
1523
this.subjectName = subjectName;
1624
this.evaluations = evaluations;
25+
this.students = students;
1726
}
1827

1928
@Getter
20-
public static class EvaluationMethodScoreDto {
29+
public static class EvaluationDto {
30+
31+
@Schema(description = "평가 항목 ID", example = "1")
2132
private final Long evaluationId;
22-
private final String title;
23-
private final String examType;
24-
private final double weight;
25-
private final double fullScore;
2633

27-
private List<StudentScoreDto> scores;
34+
@Schema(description = "항목 이름", example = "기말고사")
35+
private final String title;
2836

2937
@Builder
30-
private EvaluationMethodScoreDto( Long evaluationId,String title, String examType, double weight, double fullScore, List<StudentScoreDto> scores) {
38+
private EvaluationDto(Long evaluationId, String title) {
3139
this.evaluationId = evaluationId;
3240
this.title = title;
33-
this.examType = examType;
34-
this.weight = weight;
35-
this.fullScore = fullScore;
41+
}
42+
}
43+
44+
@Getter
45+
public static class StudentScoreDto {
46+
47+
@Schema(description = "학생 이름", example = "홍길동")
48+
private final String studentName;
49+
50+
@Schema(description = "출석번호", example = "1")
51+
private final int number;
52+
53+
@Schema(description = "항목별 점수")
54+
private final List<ScoreItemDto> scores;
55+
56+
@Schema(description = "총 점수", example = "96.0")
57+
private final double rawTotal;
58+
59+
@Schema(description = "총 환산점수", example = "78.2")
60+
private final double weightedTotal;
61+
62+
@Schema(description = "전체 평균 점수", example = "79.4")
63+
private final double average;
64+
65+
@Schema(description = "표준편차", example = "5.3")
66+
private final double stdDev;
67+
68+
@Schema(description = "석차", example = "3")
69+
private final int rank;
70+
71+
@Schema(description = "석차등급", example = "2")
72+
private final int grade;
73+
74+
@Schema(description = "성취도", example = "B")
75+
private final String achievementLevel;
76+
77+
78+
@Builder
79+
private StudentScoreDto(String studentName, int number, List<ScoreItemDto> scores,
80+
double rawTotal, double weightedTotal, double average, double stdDev, int rank, int grade, String achievementLevel) {
81+
this.studentName = studentName;
82+
this.number = number;
3683
this.scores = scores;
84+
this.rawTotal = rawTotal;
85+
this.weightedTotal = weightedTotal;
86+
this.average = average;
87+
this.stdDev = stdDev;
88+
this.rank = rank;
89+
this.grade = grade;
90+
this.achievementLevel = achievementLevel;
3791
}
92+
}
93+
94+
@Getter
95+
public static class ScoreItemDto {
96+
97+
@Schema(description = "평가 항목 ID", example = "1")
98+
private final Long evaluationId;
99+
100+
@Schema(description = "원점수", example = "74.0")
101+
private final Double rawScore;
102+
103+
@Schema(description = "환산점수", example = "51.8")
104+
private final Double weightedScore;
38105

39-
@Getter
40106
@Builder
41-
public static class StudentScoreDto {
42-
private final String studentName;
43-
private final int number;
44-
private final Double rawScore;
45-
private final Double weightedScore;
107+
public ScoreItemDto(Long evaluationId, Double rawScore, Double weightedScore) {
108+
this.evaluationId = evaluationId;
109+
this.rawScore = rawScore;
110+
this.weightedScore = weightedScore;
46111
}
47112
}
48113
}

src/main/java/com/neeis/neeis/domain/score/service/ScoreService.java

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,27 @@
1010
import com.neeis.neeis.domain.score.ScoreRepository;
1111
import com.neeis.neeis.domain.score.dto.req.ScoreRequestDto;
1212
import com.neeis.neeis.domain.score.dto.res.ScoreSummaryBySubjectDto;
13+
import com.neeis.neeis.domain.scoreSummary.ScoreSummary;
1314
import com.neeis.neeis.domain.scoreSummary.service.ScoreSummaryService;
1415
import com.neeis.neeis.domain.subject.Subject;
1516
import com.neeis.neeis.domain.subject.service.SubjectService;
1617
import com.neeis.neeis.domain.teacher.Teacher;
1718
import com.neeis.neeis.domain.teacher.service.TeacherService;
1819
import com.neeis.neeis.domain.teacherSubject.service.TeacherSubjectService;
20+
import com.neeis.neeis.global.exception.CustomException;
21+
import com.neeis.neeis.global.exception.ErrorCode;
1922
import lombok.RequiredArgsConstructor;
23+
import lombok.extern.slf4j.Slf4j;
2024
import org.springframework.stereotype.Service;
2125
import org.springframework.transaction.annotation.Transactional;
2226

23-
import java.util.ArrayList;
24-
import java.util.HashMap;
25-
import java.util.List;
26-
import java.util.Map;
27+
import java.util.*;
2728
import java.util.stream.Collectors;
2829

2930
@Service
3031
@RequiredArgsConstructor
3132
@Transactional(readOnly = true)
33+
@Slf4j
3234
public class ScoreService {
3335
private final ScoreRepository scoreRepository;
3436
private final TeacherService teacherService;
@@ -63,37 +65,48 @@ public List<ScoreSummaryBySubjectDto> getScoreSummaryBySubject(String username,
6365

6466
if (evaluations.isEmpty()) continue;
6567

66-
List<ScoreSummaryBySubjectDto.EvaluationMethodScoreDto> evalList = new ArrayList<>();
67-
68-
for (EvaluationMethod eval : evaluations) {
69-
List<Score> scores = scoreRepository.findAllByEvaluationMethod(eval);
70-
71-
List<ScoreSummaryBySubjectDto.EvaluationMethodScoreDto.StudentScoreDto> scoreDtos = scores.stream()
72-
.filter(score -> students.contains(score.getStudent()))
73-
.map(score -> {
74-
ClassroomStudent s = score.getStudent();
75-
return ScoreSummaryBySubjectDto.EvaluationMethodScoreDto.StudentScoreDto.builder()
76-
.studentName(s.getStudent().getName())
77-
.number(s.getNumber())
78-
.rawScore(score.getRawScore())
79-
.weightedScore(score.getWeightedScore())
80-
.build();
81-
})
82-
.collect(Collectors.toList());
83-
84-
evalList.add(ScoreSummaryBySubjectDto.EvaluationMethodScoreDto.builder()
85-
.evaluationId(eval.getId())
86-
.title(eval.getTitle())
87-
.examType(eval.getExamType().name())
88-
.weight(eval.getWeight())
89-
.fullScore(eval.getFullScore())
90-
.scores(scoreDtos)
68+
List<ScoreSummaryBySubjectDto.EvaluationDto> evaluationDtos = evaluations.stream()
69+
.map(eval -> ScoreSummaryBySubjectDto.EvaluationDto.builder()
70+
.evaluationId(eval.getId())
71+
.title(eval.getTitle())
72+
.build())
73+
.toList();
74+
75+
List<ScoreSummaryBySubjectDto.StudentScoreDto> studentDtos = new ArrayList<>();
76+
77+
for (ClassroomStudent cs : students) {
78+
List<ScoreSummaryBySubjectDto.ScoreItemDto> scoreItems = new ArrayList<>();
79+
80+
for (EvaluationMethod eval : evaluations) {
81+
scoreRepository.findByEvaluationMethodAndStudent(eval, cs).ifPresent(score -> {
82+
scoreItems.add(ScoreSummaryBySubjectDto.ScoreItemDto.builder()
83+
.evaluationId(eval.getId())
84+
.rawScore(score.getRawScore())
85+
.weightedScore(score.getWeightedScore())
86+
.build());
87+
});
88+
}
89+
90+
ScoreSummary summary = scoreSummaryService.findByStudentAndSubject(cs.getId(), subject.getId());
91+
92+
studentDtos.add(ScoreSummaryBySubjectDto.StudentScoreDto.builder()
93+
.studentName(cs.getStudent().getName())
94+
.number(cs.getNumber())
95+
.scores(scoreItems)
96+
.rawTotal(summary.getSumScore())
97+
.weightedTotal(summary.getOriginalScore())
98+
.average(summary.getAverage())
99+
.stdDev(summary.getStdDeviation())
100+
.rank(summary.getRank())
101+
.grade(summary.getGrade())
102+
.achievementLevel(summary.getAchievementLevel())
91103
.build());
92-
}
93104

105+
}
94106
result.add(ScoreSummaryBySubjectDto.builder()
95107
.subjectName(subject.getName())
96-
.evaluations(evalList)
108+
.evaluations(evaluationDtos)
109+
.students(studentDtos)
97110
.build());
98111
}
99112

src/main/java/com/neeis/neeis/domain/scoreSummary/ScoreSummaryRepository.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@
33
import com.neeis.neeis.domain.classroomStudent.ClassroomStudent;
44
import com.neeis.neeis.domain.subject.Subject;
55
import org.springframework.data.jpa.repository.JpaRepository;
6+
import org.springframework.data.jpa.repository.Query;
7+
import org.springframework.data.repository.query.Param;
68

79
import java.util.List;
10+
import java.util.Optional;
811

912
public interface ScoreSummaryRepository extends JpaRepository<ScoreSummary, Long> {
1013
List<ScoreSummary> findAllByClassroomStudent(ClassroomStudent students);
1114
void deleteBySubjectAndClassroomStudentIn(Subject subject, List<ClassroomStudent> students);
15+
@Query(value = "SELECT * FROM score_summary s WHERE s.classroom_student_id = :studentId AND s.subject_id = :subjectId", nativeQuery = true)
16+
Optional<ScoreSummary> findByStudentAndSubject(@Param("studentId") Long studentId,
17+
@Param("subjectId") Long subjectId);
1218
}
1319

src/main/java/com/neeis/neeis/domain/scoreSummary/service/ScoreSummaryService.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313
import com.neeis.neeis.domain.scoreSummary.ScoreSummaryRepository;
1414
import com.neeis.neeis.domain.scoreSummary.dto.StudentScoreSummaryDto;
1515
import com.neeis.neeis.domain.scoreSummary.dto.SubjectScoreDto;
16+
import com.neeis.neeis.domain.student.Student;
1617
import com.neeis.neeis.domain.subject.Subject;
1718
import com.neeis.neeis.domain.teacher.service.TeacherService;
19+
import com.neeis.neeis.global.exception.CustomException;
20+
import com.neeis.neeis.global.exception.ErrorCode;
1821
import lombok.RequiredArgsConstructor;
1922
import org.springframework.stereotype.Service;
2023
import org.springframework.transaction.annotation.Transactional;
@@ -134,4 +137,9 @@ public void updateSummaryForClass(int year, int semester, int grade, int classNu
134137
}
135138
}
136139
}
140+
141+
public ScoreSummary findByStudentAndSubject(Long studentId, Long subjectId) {
142+
return scoreSummaryRepository.findByStudentAndSubject(studentId, subjectId)
143+
.orElseThrow(() -> new CustomException(ErrorCode.SCORE_SUMMARY_NOT_FOUND));
144+
}
137145
}

src/main/java/com/neeis/neeis/global/exception/ErrorCode.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,11 @@ public enum ErrorCode {
4646
EVALUATION_METHOD_NOT_FOUND(HttpStatus.NOT_FOUND, "EvaluationMethod-002", "해당 평가 방식이 존재하지 않습니다."),
4747
EXCESS_TOTAL_100(HttpStatus.BAD_REQUEST,"EvaluationMethod-003", "해당 과목의 반영 비율 총합이 100을 초과합니다."),
4848

49-
5049
SCORE_OVER_FULL(HttpStatus.BAD_REQUEST, "SCORE_001", "점수가 만점을 초과했습니다."),
51-
SCORE_NEGATIVE(HttpStatus.BAD_REQUEST, "SCORE_002", "점수가 0보다 작을 수 없습니다.");
50+
SCORE_NEGATIVE(HttpStatus.BAD_REQUEST, "SCORE_002", "점수가 0보다 작을 수 없습니다."),
51+
52+
SCORE_SUMMARY_NOT_FOUND(HttpStatus.NOT_FOUND, "Score-Summary-001", "점수 통계가 존재하지 않습니다."),
53+
5254
;
5355

5456
private final HttpStatus status;

0 commit comments

Comments
 (0)