Skip to content

Commit 42eb366

Browse files
authored
Merge pull request #45 from INU-Software-Design/NEEIS-91-feature/report
Neeis 91 feature/report
2 parents 67da110 + 6cecdec commit 42eb366

7 files changed

Lines changed: 217 additions & 16 deletions

File tree

โ€Žsrc/main/java/com/neeis/neeis/domain/scoreSummary/service/ScoreSummaryService.javaโ€Ž

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.neeis.neeis.domain.scoreSummary.dto.res.SubjectScoreDto;
1818
import com.neeis.neeis.domain.scoreSummary.dto.req.ScoreFeedbackRequestDto;
1919
import com.neeis.neeis.domain.scoreSummary.dto.req.ScoreFeedbackUpdateDto;
20+
import com.neeis.neeis.domain.student.dto.report.SubjectFeedbackDto;
2021
import com.neeis.neeis.domain.subject.Subject;
2122
import com.neeis.neeis.domain.teacher.Teacher;
2223
import com.neeis.neeis.domain.teacher.service.TeacherService;
@@ -241,6 +242,49 @@ public ScoreFeedbackDto getFeedback(String username, Long scoreSummaryId) {
241242
return ScoreFeedbackDto.toDto(summary);
242243
}
243244

245+
/**
246+
* ํŠน์ • ํ•™์ƒ์— ๋Œ€ํ•ด โ€œํ•ด๋‹น ํ•™๊ธฐ(์—ฐ๋„, ํ•™๊ธฐ, ํ•™๋…„, ๋ฐ˜, ๋ฒˆํ˜ธ)โ€์— ์†ํ•œ ๊ณผ๋ชฉ๋“ค์˜ ํ”ผ๋“œ๋ฐฑ์„
247+
* SubjectFeedbackDto ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
248+
*/
249+
public List<SubjectFeedbackDto> getSubjectFeedbacks(
250+
String username,
251+
int year,
252+
int semester,
253+
int grade,
254+
int classNum,
255+
int number
256+
) {
257+
258+
ClassroomStudent classroomStudent = checkValidate(username, year, grade, classNum, number);
259+
260+
// 2. ํ•ด๋‹น ํ•™๊ธฐ(์—ฐ๋„, ํ•™๊ธฐ, ํ•™๋…„)์— ์†ํ•œ โ€œ๊ณผ๋ชฉ ๋ชฉ๋กโ€ ์กฐํšŒ
261+
List<Subject> subjectsInThisTerm = evaluationMethodService
262+
.findSubject(year, semester, grade);
263+
264+
// ๊ณผ๋ชฉ ์ด๋ฆ„๋งŒ ๋ชจ์•„์„œ ํ•„ํ„ฐ๋ง์šฉ Set์œผ๋กœ ์ค€๋น„
265+
Set<String> subjectNamesInThisTerm = subjectsInThisTerm.stream()
266+
.map(Subject::getName)
267+
.collect(Collectors.toSet());
268+
269+
// 3. DB์—์„œ ์ด ํ•™์ƒ์˜ ๋ชจ๋“  ScoreSummary(๊ณผ๋ชฉ๋ณ„ ์š”์•ฝ)๋ฅผ ์กฐํšŒ
270+
List<ScoreSummary> allSummaries = scoreSummaryRepository
271+
.findAllByClassroomStudent(classroomStudent);
272+
273+
// 4. โ€œ์ด ํ•™๊ธฐ์— ์†ํ•œ ๊ณผ๋ชฉ(subjectNamesInThisTerm)์— ํ•ด๋‹นํ•˜๋Š”โ€ ScoreSummary๋งŒ ํ•„ํ„ฐ๋ง
274+
return allSummaries.stream()
275+
.filter(summary -> subjectNamesInThisTerm.contains(
276+
summary.getSubject().getName()
277+
))
278+
.map(summary -> {
279+
// 5. SubjectFeedbackDto๋กœ ๋ณ€ํ™˜: (๊ณผ๋ชฉ๋ช…, ํ”ผ๋“œ๋ฐฑ ๋‚ด์šฉ)
280+
return SubjectFeedbackDto.builder()
281+
.subjectName(summary.getSubject().getName())
282+
.feedback(summary.getFeedback())
283+
.build();
284+
})
285+
.toList();
286+
}
287+
244288

245289
/**
246290
* ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๋Š” ๊ธฐ์กด ๋ฉ”์„œ๋“œ (ํ•˜์œ„ ํ˜ธํ™˜์„ฑ ์œ ์ง€)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package com.neeis.neeis.domain.student.dto.report;
2+
3+
public class FeedbackReportDto {
4+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.neeis.neeis.domain.student.dto.report;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Builder;
5+
import lombok.Getter;
6+
import lombok.NoArgsConstructor;
7+
8+
@Getter
9+
@Builder
10+
@NoArgsConstructor
11+
@AllArgsConstructor
12+
public class SubjectFeedbackDto {
13+
private String subjectName;
14+
private String feedback;
15+
}

โ€Žsrc/main/java/com/neeis/neeis/domain/student/dto/req/StudentReportRequestDto.javaโ€Ž

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,9 @@ public class StudentReportRequestDto {
1717
private int semester;
1818

1919
// ํฌํ•จํ•  ์„น์…˜ ์„ ํƒ
20-
private boolean includeAttendance = false;
20+
private boolean includeAttendance = true;
2121
private boolean includeGrades = true; // ScoreSummary ๊ธฐ๋ฐ˜
22-
private boolean includeCounseling = false;
23-
private boolean includeBehavior = false;
24-
25-
// ๊ธฐ๊ฐ„ ํ•„ํ„ฐ๋ง
26-
private LocalDate startDate;
27-
private LocalDate endDate;
22+
private boolean includeCounseling = true;
23+
private boolean includeBehavior = true;
24+
private boolean includeFeedback = true;
2825
}

โ€Žsrc/main/java/com/neeis/neeis/domain/student/dto/res/StudentReportResponseDto.javaโ€Ž

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package com.neeis.neeis.domain.student.dto.res;
22

3+
import com.neeis.neeis.domain.attendance.dto.res.AttendanceFeedbackResDto;
34
import com.neeis.neeis.domain.student.dto.report.*;
45
import lombok.AllArgsConstructor;
56
import lombok.Builder;
67
import lombok.Getter;
78
import java.time.LocalDateTime;
9+
import java.util.List;
810

911
@Getter
1012
@Builder
@@ -15,6 +17,8 @@ public class StudentReportResponseDto {
1517
private GradesReportDto grades; // ์ƒˆ๋กœ ์ƒ์„ฑ
1618
private CounselingReportDto counseling; // ์ƒˆ๋กœ ์ƒ์„ฑ
1719
private BehaviorReportDto behavior; // ์ƒˆ๋กœ ์ƒ์„ฑ
18-
private LocalDateTime generatedAt;
1920
private ParentReportDto parents;
21+
private List<SubjectFeedbackDto> scoreFeedbacks; // ๊ณผ๋ชฉ๋ณ„ ์„ฑ์  ํ”ผ๋“œ๋ฐฑ ๋ชฉ๋ก
22+
private AttendanceFeedbackResDto attendanceFeedback; // ์ „์ฒด ์ถœ๊ฒฐ ํ”ผ๋“œ๋ฐฑ (๊ต์‚ฌ๊ฐ€ ์ž‘์„ฑํ•œ ํ•œ ์ค„ ํ”ผ๋“œ๋ฐฑ)
23+
private LocalDateTime generatedAt;
2024
}

โ€Žsrc/main/java/com/neeis/neeis/domain/student/service/StudentReportService.javaโ€Ž

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
package com.neeis.neeis.domain.student.service;
22

3+
import com.neeis.neeis.domain.attendance.dto.res.AttendanceFeedbackResDto;
34
import com.neeis.neeis.domain.attendance.service.AttendanceService;
45
import com.neeis.neeis.domain.behavior.service.BehaviorService;
56
import com.neeis.neeis.domain.counsel.dto.res.CounselDetailDto;
67
import com.neeis.neeis.domain.counsel.service.CounselService;
78
import com.neeis.neeis.domain.parent.ParentService;
8-
import com.neeis.neeis.domain.student.dto.report.AttendanceReportDto;
9-
import com.neeis.neeis.domain.student.dto.report.BehaviorReportDto;
10-
import com.neeis.neeis.domain.student.dto.report.CounselingReportDto;
11-
import com.neeis.neeis.domain.student.dto.report.GradesReportDto;
9+
import com.neeis.neeis.domain.student.dto.report.*;
1210
import com.neeis.neeis.domain.student.dto.req.StudentReportRequestDto;
1311
import com.neeis.neeis.domain.student.dto.res.*;
1412
import com.neeis.neeis.domain.classroomStudent.ClassroomStudent;
@@ -94,6 +92,30 @@ public StudentReportResponseDto generateStudentReport(StudentReportRequestDto re
9492
builder.behavior(createBehaviorReport(classroomStudent, requestDto));
9593
}
9694

95+
if(requestDto.isIncludeFeedback()){
96+
List<SubjectFeedbackDto> feedbackList = scoreSummaryService.getSubjectFeedbacks(
97+
classroomStudent.getStudent().getUser().getUsername(),
98+
requestDto.getYear(),
99+
requestDto.getSemester(),
100+
classroomStudent.getClassroom().getGrade(),
101+
classroomStudent.getClassroom().getClassNum(),
102+
classroomStudent.getNumber()
103+
);
104+
builder.scoreFeedbacks(feedbackList);
105+
}
106+
107+
if (requestDto.isIncludeFeedback()){
108+
AttendanceFeedbackResDto attendanceFeedbackDto = attendanceService.getFeedback(
109+
classroomStudent.getStudent().getUser().getUsername(),
110+
requestDto.getYear(),
111+
classroomStudent.getClassroom().getGrade(),
112+
classroomStudent.getClassroom().getClassNum(),
113+
classroomStudent.getNumber()
114+
);
115+
builder.attendanceFeedback(attendanceFeedbackDto);
116+
}
117+
118+
97119
// 6. ์ƒ์„ฑ ์‹œ๊ฐ„
98120
builder.generatedAt(LocalDateTime.now());
99121

@@ -103,6 +125,8 @@ public StudentReportResponseDto generateStudentReport(StudentReportRequestDto re
103125
return result;
104126
}
105127

128+
129+
106130
/**
107131
* TODO: ํ˜„์žฌ ๋กœ๊ทธ์ธํ•œ ํ•™์ƒ์˜ ๋ณด๊ณ ์„œ ์ƒ์„ฑ (์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์šฉ)
108132
*/
@@ -113,6 +137,11 @@ public StudentReportResponseDto generateMyStudentReport(String username, Student
113137
User user = userService.getUser(username);
114138
Student student = studentService.findByUser(user);
115139

140+
// ํ•™์ƒ์€ ์ž์‹ ๊ฒƒ๋งŒ ์กฐํšŒ ๊ฐ€๋Šฅ
141+
if (!student.getId().equals(requestDto.getStudentId())) {
142+
throw new CustomException(ErrorCode.HANDLE_ACCESS_DENIED);
143+
}
144+
116145
// ์š”์ฒญ DTO์— ํ•™์ƒ ID ์„ค์ •
117146
requestDto.setStudentId(student.getId());
118147

โ€Žsrc/main/java/com/neeis/neeis/global/report/service/PdfGeneratorService.javaโ€Ž

Lines changed: 112 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.itextpdf.layout.properties.HorizontalAlignment;
1818
import com.itextpdf.layout.properties.TextAlignment;
1919
import com.itextpdf.layout.properties.UnitValue;
20+
import com.neeis.neeis.domain.attendance.dto.res.AttendanceFeedbackResDto;
2021
import com.neeis.neeis.domain.scoreSummary.dto.res.SubjectScoreDto;
2122
import com.neeis.neeis.domain.student.dto.report.*;
2223
import lombok.RequiredArgsConstructor;
@@ -39,6 +40,7 @@
3940
import java.io.InputStream;
4041
import java.nio.charset.StandardCharsets;
4142
import java.time.format.DateTimeFormatter;
43+
import java.util.List;
4244
import java.util.concurrent.atomic.AtomicInteger;
4345

4446
@Service
@@ -101,6 +103,14 @@ public byte[] generateStudentReportPdf(StudentReportResponseDto report) {
101103
addBehaviorSection(document, report.getBehavior(), font, isKorean, sectionNumber.getAndIncrement());
102104
}
103105

106+
if (report.getScoreFeedbacks() != null) {
107+
addScoreFeedbackSection(document, report.getScoreFeedbacks(), font, isKorean, sectionNumber.getAndIncrement());
108+
}
109+
110+
if (report.getAttendanceFeedback() != null) {
111+
addAttendanceFeedbackSection(document, report.getAttendanceFeedback(), font, isKorean, sectionNumber.getAndIncrement());
112+
}
113+
104114
// Document ๋‹ซ๊ธฐ
105115
document.close();
106116
document = null; // null๋กœ ์„ค์ •ํ•˜์—ฌ finally์—์„œ ์ค‘๋ณต close ๋ฐฉ์ง€
@@ -330,7 +340,7 @@ private void addAttendanceSection(Document document, AttendanceReportDto attenda
330340
.setBold()
331341
.setBackgroundColor(new DeviceRgb(52, 152, 219))
332342
.setFontColor(ColorConstants.WHITE)
333-
.setPadding(10)
343+
.setPadding(5)
334344
.setMarginTop(20)
335345
.setMarginBottom(10);
336346
document.add(title);
@@ -375,7 +385,7 @@ private void addGradesSection(Document document, GradesReportDto grades, PdfFont
375385
.setBold()
376386
.setBackgroundColor(new DeviceRgb(52, 152, 219))
377387
.setFontColor(ColorConstants.WHITE)
378-
.setPadding(10)
388+
.setPadding(5)
379389
.setMarginTop(20)
380390
.setMarginBottom(10);
381391
document.add(title);
@@ -569,7 +579,7 @@ private void addCounselingSection(Document document, CounselingReportDto counsel
569579
.setBold()
570580
.setBackgroundColor(new DeviceRgb(52, 152, 219))
571581
.setFontColor(ColorConstants.WHITE)
572-
.setPadding(10)
582+
.setPadding(5)
573583
.setMarginTop(20)
574584
.setMarginBottom(10);
575585
document.add(title);
@@ -774,7 +784,7 @@ private void addBehaviorSection(Document document, BehaviorReportDto behavior, P
774784
.setBold()
775785
.setBackgroundColor(new DeviceRgb(52, 152, 219))
776786
.setFontColor(ColorConstants.WHITE)
777-
.setPadding(10)
787+
.setPadding(5)
778788
.setMarginTop(20)
779789
.setMarginBottom(10);
780790
document.add(title);
@@ -848,6 +858,104 @@ private void addBehaviorBox(Document document, String title, String content, Pdf
848858
}
849859
}
850860

861+
/*
862+
* ์„ฑ์  ํ”ผ๋“œ๋ฐฑ
863+
* */
864+
private void addScoreFeedbackSection(Document document,
865+
List<SubjectFeedbackDto> feedbacks,
866+
PdfFont font, boolean isKorean, int sectionNumber) {
867+
try {
868+
String sectionTitle = isKorean ?
869+
sectionNumber + ". ๊ณผ๋ชฉ๋ณ„ ์„ฑ์  ํ”ผ๋“œ๋ฐฑ" :
870+
sectionNumber + ". Subject Feedback";
871+
872+
Paragraph title = new Paragraph(sectionTitle)
873+
.setFont(font)
874+
.setFontSize(14)
875+
.setBold()
876+
.setBackgroundColor(new DeviceRgb(52, 152, 219))
877+
.setFontColor(ColorConstants.WHITE)
878+
.setPadding(5)
879+
.setMarginTop(20)
880+
.setMarginBottom(10);
881+
document.add(title);
882+
883+
if (feedbacks == null || feedbacks.isEmpty()) {
884+
String noDataText = isKorean ?
885+
"๋“ฑ๋ก๋œ ํ”ผ๋“œ๋ฐฑ์ด ์—†์Šต๋‹ˆ๋‹ค." :
886+
"No feedback available.";
887+
document.add(new Paragraph(noDataText).setFont(font).setFontSize(11).setItalic());
888+
return;
889+
}
890+
891+
// ํ…Œ์ด๋ธ”: 2์—ด (๊ณผ๋ชฉ๋ช… | ํ”ผ๋“œ๋ฐฑ ๋‚ด์šฉ)
892+
Table table = new Table(UnitValue.createPercentArray(new float[]{1f, 3f}))
893+
.useAllAvailableWidth()
894+
.setMarginBottom(15);
895+
896+
// ํ—ค๋”
897+
String subjectHeader = isKorean ? "๊ณผ๋ชฉ๋ช…" : "Subject";
898+
String feedbackHeader = isKorean ? "ํ”ผ๋“œ๋ฐฑ ๋‚ด์šฉ" : "Feedback";
899+
table.addHeaderCell(createHeaderCell(subjectHeader, font));
900+
table.addHeaderCell(createHeaderCell(feedbackHeader, font));
901+
902+
// ๋ฐ์ดํ„ฐ ํ–‰
903+
for (SubjectFeedbackDto dto : feedbacks) {
904+
table.addCell(createDataCell(dto.getSubjectName(), font));
905+
String feedbackText = dto.getFeedback();
906+
if (feedbackText == null || feedbackText.trim().isEmpty()) {
907+
feedbackText = "-";
908+
}
909+
table.addCell(createDataCell(feedbackText, font));
910+
}
911+
912+
document.add(table);
913+
914+
} catch (Exception e) {
915+
log.error("๊ณผ๋ชฉ๋ณ„ ์„ฑ์  ํ”ผ๋“œ๋ฐฑ ์„น์…˜ ์ถ”๊ฐ€ ์‹คํŒจ", e);
916+
}
917+
}
918+
919+
/*
920+
* ์ถœ๊ฒฐ ํ”ผ๋“œ๋ฐฑ
921+
* */
922+
private void addAttendanceFeedbackSection(Document document,
923+
AttendanceFeedbackResDto attendanceFeedback,
924+
PdfFont font, boolean isKorean, int sectionNumber) {
925+
try {
926+
String sectionTitle = isKorean ?
927+
sectionNumber + ". ์ถœ๊ฒฐ ํ”ผ๋“œ๋ฐฑ" :
928+
sectionNumber + ". Attendance Feedback";
929+
930+
Paragraph title = new Paragraph(sectionTitle)
931+
.setFont(font)
932+
.setFontSize(14)
933+
.setBold()
934+
.setBackgroundColor(new DeviceRgb(52, 152, 219))
935+
.setFontColor(ColorConstants.WHITE)
936+
.setPadding(5)
937+
.setMarginTop(20)
938+
.setMarginBottom(10);
939+
document.add(title);
940+
941+
if (attendanceFeedback == null || attendanceFeedback.getFeedback() == null || attendanceFeedback.getFeedback().isEmpty()) {
942+
String noDataText = isKorean ?
943+
"๋“ฑ๋ก๋œ ์ถœ๊ฒฐ ํ”ผ๋“œ๋ฐฑ์ด ์—†์Šต๋‹ˆ๋‹ค." :
944+
"No attendance feedback available.";
945+
document.add(new Paragraph(noDataText).setFont(font).setFontSize(11).setItalic());
946+
return;
947+
}
948+
949+
// ํ”ผ๋“œ๋ฐฑ ๋‚ด์šฉ์„ ๋ฐ•์Šค ํ˜•ํƒœ๋กœ ํ‘œ์‹œ
950+
addBehaviorBox(document,
951+
isKorean ? "์ถœ๊ฒฐ ํ”ผ๋“œ๋ฐฑ ๋‚ด์šฉ" : "Feedback Content",
952+
attendanceFeedback.getFeedback(),
953+
font, isKorean);
954+
955+
} catch (Exception e) {
956+
log.error("์ถœ๊ฒฐ ํ”ผ๋“œ๋ฐฑ ์„น์…˜ ์ถ”๊ฐ€ ์‹คํŒจ", e);
957+
}
958+
}
851959

852960
private void addTableRow(Table table, String label1, String value1, String label2, String value2, PdfFont font) {
853961
table.addCell(createLabelCell(sanitizeText(label1), font));

0 commit comments

Comments
ย (0)