Skip to content

Commit d68ebaa

Browse files
authored
Refactor/KD-55 GraduationUser 상세 조회 API가 졸업 상태를 포함하도록 수정 (#299)
* fix: capstone_completion 컬럼이 없는 오류 수정 * refactor: 졸업 대상자 상세 조회 API가 GraduationuserStatusResponse를 포함하도록 수정 * fix: data.sql의 graduation_type 컬럼 데이터를 CERTIFICATE와 THESIS로 변경 * refactor: 상세 조회 시 졸업 상태가 각 파일의 제출일을 포함하도록 수정 * fix: 테스트 코드 오류 수정 * fix: Thesis, Certificate 서비스 충돌 오류 수정
1 parent 890ad2b commit d68ebaa

File tree

12 files changed

+130
-52
lines changed

12 files changed

+130
-52
lines changed

aics-admin/src/main/java/kgu/developers/admin/graduationUser/application/GraduationUserAdminFacade.java

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
import kgu.developers.common.response.PaginatedListResponse;
1717
import kgu.developers.domain.certificate.application.command.CertificateCommandService;
1818
import kgu.developers.domain.certificate.application.query.CertificateQueryService;
19+
import kgu.developers.domain.certificate.domain.Certificate;
1920
import kgu.developers.domain.graduationUser.application.command.GraduationUserCommandService;
2021
import kgu.developers.domain.graduationUser.application.query.GraduationUserQueryService;
2122
import kgu.developers.domain.graduationUser.domain.GraduationType;
2223
import kgu.developers.domain.graduationUser.domain.GraduationUser;
2324
import kgu.developers.domain.thesis.application.command.ThesisCommandService;
2425
import kgu.developers.domain.thesis.application.query.ThesisQueryService;
26+
import kgu.developers.domain.thesis.domain.Thesis;
2527
import lombok.RequiredArgsConstructor;
2628
import org.springframework.data.domain.Pageable;
2729
import org.springframework.stereotype.Component;
@@ -90,36 +92,37 @@ private GraduationUserStatusResponse buildSubmissionStatus(GraduationUser user)
9092
}
9193

9294
private GraduationUserStatusResponse.Certificate buildCertificateStatus(Long certificateId) {
93-
boolean submitted = certificateId != null;
94-
boolean approval = false;
95-
if(submitted) {
96-
approval = certificateQueryService.isApproved(certificateId);
95+
if (certificateId == null) {
96+
return GraduationUserStatusResponse.Certificate.of(GraduationType.CERTIFICATE,false,false,null);
9797
}
9898

99-
return new GraduationUserStatusResponse.Certificate("CERTIFICATE", submitted, approval);
99+
Certificate certificate = certificateQueryService.getById(certificateId);
100+
101+
return GraduationUserStatusResponse.Certificate.of(GraduationType.CERTIFICATE, true, certificate.isApproved(), certificate.getCreatedAt());
100102
}
101103

102104
private GraduationUserStatusResponse.Thesis buildThesisStatus(Long middleThesisId, Long finalThesisId) {
103105

104-
boolean midThesisSubmitted = middleThesisId != null;
105-
boolean midThesisapproval = false;
106-
if(midThesisSubmitted) {
107-
midThesisapproval = thesisQueryService.isApproved(middleThesisId);
108-
}
106+
GraduationUserStatusResponse.Thesis.Middle midThesisStatus;
107+
GraduationUserStatusResponse.Thesis.Final finalThesisStatus;
109108

110-
GraduationUserStatusResponse.Thesis.Middle midStatus =
111-
new GraduationUserStatusResponse.Thesis.Middle(midThesisSubmitted,midThesisapproval);
109+
if(middleThesisId == null) {
110+
midThesisStatus = GraduationUserStatusResponse.Thesis.Middle.of(false, false, null);
111+
} else {
112+
Thesis midThesis = thesisQueryService.getById(middleThesisId);
112113

113-
boolean finalThesisSubmitted = finalThesisId != null;
114-
boolean finalThesisapproval = false;
115-
if(finalThesisSubmitted) {
116-
finalThesisapproval = thesisQueryService.isApproved(finalThesisId);
114+
midThesisStatus = GraduationUserStatusResponse.Thesis.Middle.of(true, midThesis.isApproved(), midThesis.getCreatedAt());
117115
}
118116

119-
GraduationUserStatusResponse.Thesis.Final finalStatus =
120-
new GraduationUserStatusResponse.Thesis.Final(finalThesisSubmitted,finalThesisapproval);
117+
if(finalThesisId == null) {
118+
finalThesisStatus = GraduationUserStatusResponse.Thesis.Final.of(false, false, null);
119+
} else {
120+
Thesis midThesis = thesisQueryService.getById(middleThesisId);
121+
122+
finalThesisStatus = GraduationUserStatusResponse.Thesis.Final.of(true, midThesis.isApproved(), midThesis.getCreatedAt());
123+
}
121124

122-
return new GraduationUserStatusResponse.Thesis("THESIS", midStatus, finalStatus);
125+
return GraduationUserStatusResponse.Thesis.of(GraduationType.THESIS, midThesisStatus, finalThesisStatus);
123126
}
124127

125128
public void deleteGraduationUser(Long id) {
@@ -128,7 +131,9 @@ public void deleteGraduationUser(Long id) {
128131
}
129132

130133
public GraduationUserDetailResponse getGraduationUserById(Long graduationUserId) {
131-
return GraduationUserDetailResponse.from(graduationUserQueryService.getById(graduationUserId));
134+
GraduationUser graduationUser = graduationUserQueryService.getById(graduationUserId);
135+
GraduationUserStatusResponse status = buildSubmissionStatus(graduationUser);
136+
return GraduationUserDetailResponse.from(graduationUser, status);
132137
}
133138

134139
public GraduationUserBatchDeleteResponse deleteGraduationUsers(GraduationUserBatchDeleteRequest request) {

aics-admin/src/main/java/kgu/developers/admin/graduationUser/presentation/response/GraduationUserDetailResponse.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,30 @@ public record GraduationUserDetailResponse(
3131
String major,
3232

3333
@Schema(description = "캡스톤 이수 여부", example = "true", requiredMode = REQUIRED)
34-
Boolean capstoneCompletion
34+
Boolean capstoneCompletion,
35+
36+
@Schema(
37+
description = "졸업 요건 제출 및 승인 상태 (자격증 또는 논문)",
38+
example = "{"
39+
+ "\"type\": \"THESIS\", "
40+
+ "\"midThesis\": {"
41+
+ "\"submitted\": true, "
42+
+ "\"approval\": true, "
43+
+ "\"createdAt\": \"2024-08-01\" "
44+
+ "}, "
45+
+ "\"finalThesis\": {"
46+
+ "\"submitted\": false, "
47+
+ "\"approval\": false, "
48+
+ "\"createdAt\": \"null\" "
49+
+ "}"
50+
+ "}",
51+
requiredMode = REQUIRED
52+
)
53+
GraduationUserStatusResponse status
3554
) {
3655
public static GraduationUserDetailResponse from(
37-
GraduationUser graduationUser
56+
GraduationUser graduationUser,
57+
GraduationUserStatusResponse status
3858
) {
3959
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
4060
return GraduationUserDetailResponse.builder()
@@ -45,6 +65,7 @@ public static GraduationUserDetailResponse from(
4565
.advisor(graduationUser.getAdvisorProfessor())
4666
.major(graduationUser.getDepartment())
4767
.capstoneCompletion(graduationUser.getCapstoneCompletion())
68+
.status(status)
4869
.build();
4970
}
5071
}

aics-admin/src/main/java/kgu/developers/admin/graduationUser/presentation/response/GraduationUserStatusResponse.java

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
package kgu.developers.admin.graduationUser.presentation.response;
22

33
import io.swagger.v3.oas.annotations.media.Schema;
4+
import kgu.developers.domain.graduationUser.domain.GraduationType;
5+
import lombok.Builder;
6+
import org.springframework.format.annotation.DateTimeFormat;
7+
8+
import java.time.LocalDateTime;
9+
import java.time.format.DateTimeFormatter;
10+
11+
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
412

513
/**
614
* 졸업 대상자 상태 응답 인터페이스
@@ -11,6 +19,7 @@ public sealed interface GraduationUserStatusResponse
1119
permits GraduationUserStatusResponse.Certificate,
1220
GraduationUserStatusResponse.Thesis {
1321

22+
@Builder
1423
@Schema(description = "자격증 제출 상태")
1524
record Certificate(
1625
@Schema(description = "졸업 타입", example = "CERTIFICATE")
@@ -20,10 +29,25 @@ record Certificate(
2029
boolean submitted,
2130

2231
@Schema(description = "승인 여부", example = "false")
23-
boolean approval
32+
boolean approval,
33+
34+
@Schema(description = "제출일", example = "2024-08-11", requiredMode = REQUIRED)
35+
@DateTimeFormat(pattern = "yyyy-MM-dd")
36+
String createdAt
37+
2438
) implements GraduationUserStatusResponse {
39+
public static Certificate of(GraduationType type, boolean submitted, boolean approval, LocalDateTime createdAt) {
40+
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
41+
return Certificate.builder()
42+
.type(type.name())
43+
.submitted(submitted)
44+
.approval(approval)
45+
.createdAt(createdAt.format(formatter))
46+
.build();
47+
}
2548
}
2649

50+
@Builder
2751
@Schema(description = "논문 제출 상태")
2852
record Thesis(
2953
@Schema(description = "졸업 타입", example = "THESIS")
@@ -35,23 +59,58 @@ record Thesis(
3559
@Schema(description = "최종 논문 상태")
3660
Final finalThesis
3761
) implements GraduationUserStatusResponse {
62+
public static Thesis of(GraduationType type, Middle midThesis, Final finalThesis) {
63+
return Thesis.builder()
64+
.type(type.name())
65+
.midThesis(midThesis)
66+
.finalThesis(finalThesis)
67+
.build();
68+
}
3869

70+
@Builder
3971
@Schema(description = "중간 논문 제출 상태")
4072
public record Middle(
4173
@Schema(description = "파일 제출 여부", example = "true")
4274
boolean submitted,
4375

4476
@Schema(description = "승인 여부", example = "true")
45-
boolean approval
46-
) {}
77+
boolean approval,
78+
79+
@Schema(description = "제출일", example = "2024-08-11", requiredMode = REQUIRED)
80+
@DateTimeFormat(pattern = "yyyy-MM-dd")
81+
String createdAt
82+
) {
83+
public static Middle of(boolean submitted, boolean approval, LocalDateTime createdAt) {
84+
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
85+
return Middle.builder()
86+
.submitted(submitted)
87+
.approval(approval)
88+
.createdAt(createdAt.format(formatter))
89+
.build();
90+
}
91+
}
4792

93+
@Builder
4894
@Schema(description = "최종 논문 제출 상태")
4995
public record Final(
5096
@Schema(description = "파일 제출 여부", example = "false")
5197
boolean submitted,
5298

5399
@Schema(description = "승인 여부", example = "false")
54-
boolean approval
55-
) {}
100+
boolean approval,
101+
102+
@Schema(description = "제출일", example = "2024-08-11", requiredMode = REQUIRED)
103+
@DateTimeFormat(pattern = "yyyy-MM-dd")
104+
String createdAt
105+
) {
106+
public static Final of(boolean submitted, boolean approval, LocalDateTime createdAt) {
107+
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
108+
return Final.builder()
109+
.submitted(submitted)
110+
.approval(approval)
111+
.createdAt(createdAt.format(formatter))
112+
.build();
113+
}
114+
}
56115
}
57116
}

aics-admin/src/main/java/kgu/developers/admin/graduationUser/presentation/response/GraduationUserSummaryResponse.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,23 @@ public record GraduationUserSummaryResponse(
3333
+ "\"type\": \"THESIS\", "
3434
+ "\"midThesis\": {"
3535
+ "\"submitted\": true, "
36-
+ "\"approval\": true"
36+
+ "\"approval\": true, "
37+
+ "\"createdAt\": \"2024-08-01\" "
3738
+ "}, "
3839
+ "\"finalThesis\": {"
3940
+ "\"submitted\": false, "
40-
+ "\"approval\": false"
41+
+ "\"approval\": false, "
42+
+ "\"createdAt\": \"null\" "
4143
+ "}"
4244
+ "}",
4345
requiredMode = REQUIRED
4446
)
4547
GraduationUserStatusResponse status
4648
) {
47-
public static GraduationUserSummaryResponse of(GraduationUser graduationUser, GraduationUserStatusResponse status) {
49+
public static GraduationUserSummaryResponse of(
50+
GraduationUser graduationUser,
51+
GraduationUserStatusResponse status
52+
) {
4853
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
4954

5055
return GraduationUserSummaryResponse.builder()

aics-admin/src/testFixtures/java/graduationUser/application/GraduationUserAdminFacadeTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public class GraduationUserAdminFacadeTest {
6666
public void init() {
6767
FakeGraduationUserRepository fakeGraduationUserRepository = new FakeGraduationUserRepository();
6868
fakeUserRepository = new FakeUserRepository();
69-
GraduationUserCommandService graduationUserCommandService = new GraduationUserCommandService(fakeGraduationUserRepository, fakeUserRepository);
69+
GraduationUserCommandService graduationUserCommandService = new GraduationUserCommandService(fakeGraduationUserRepository);
7070

7171
fakeThesisRepository = new FakeThesisRepository();
7272
fakeCertificateRepository = new FakeCertificateRepository();

aics-api/src/main/resources/db/data.sql

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,14 @@ VALUES ('참여 신청 방법을 자세히 알고 싶습니다.', '2025-03-03 00
132132
('프로젝트 자료를 다운로드했습니다. 유익하네요.', '2025-03-03 07:01:00', '2025-03-03 07:01:00', 8, '202412347'),
133133
('연구 참여 방법이 있나요?', '2025-03-03 07:02:00', '2025-03-03 07:02:00', 8, '202412346');
134134

135-
INSERT INTO graduation_user (name, email, advisor_professor, graduation_type, graduation_date,
135+
INSERT INTO graduation_user (name, email, advisor_professor, graduation_type, graduation_date, capstone_completion,
136136
mid_thesis_id, final_thesis_id, certificate_id, user_id, created_at, updated_at)
137137
VALUES
138-
('김철수', 'chulsoo@kyonggi.ac.kr', '이순신', '논문', '2028-02-28', 1, 2, NULL, '202512345', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
139-
('이영희', 'younghee@kyonggi.ac.kr', '홍길동', '자격증', '2028-08-31', NULL, NULL, 1, '202512346', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
140-
('박민수', 'minsu@kyonggi.ac.kr', '정약용', '논문', '2029-02-28', 3, NULL, NULL, '202512347', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
141-
('정수진', 'sujin@kyonggi.ac.kr', '김이박', '논문', '2030-02-28', 4, 5, NULL, '202512349', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
142-
('최동욱', 'dongwook@kyonggi.ac.kr', '이교수', '자격증', '2027-08-31', NULL, NULL, 2, '202512348', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
138+
('김철수', 'chulsoo@kyonggi.ac.kr', '이순신', 'THESIS', '2028-02-01', true, 1, 2, NULL, '202512345', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
139+
('이영희', 'younghee@kyonggi.ac.kr', '홍길동', 'CERTIFICATE', '2028-08-01', true, NULL, NULL, 1, '202512346', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
140+
('박민수', 'minsu@kyonggi.ac.kr', '정약용', 'THESIS', '2029-02-01', true, 3, NULL, NULL, '202512347', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
141+
('정수진', 'sujin@kyonggi.ac.kr', '김이박', 'THESIS', '2030-02-01', false, 4, 5, NULL, '202512349', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
142+
('최동욱', 'dongwook@kyonggi.ac.kr', '이교수', 'CERTIFICATE', '2027-08-01', false, NULL, NULL, 2, '202512348', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
143143

144144
-- schedule
145145
INSERT INTO schedule (submission_type, content, start_date, end_date, created_at, updated_at)

aics-api/src/main/resources/db/schema.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ CREATE TABLE graduation_user
156156
CONSTRAINT graduation_type_check
157157
CHECK ((graduation_type)::TEXT = ANY (ARRAY ['THESIS', 'CERTIFICATE'])),
158158
graduation_date DATE,
159+
capstone_completion BOOLEAN,
159160
mid_thesis_id BIGINT,
160161
final_thesis_id BIGINT,
161162
certificate_id BIGINT,

aics-api/src/testFixtures/java/graduationUser/application/GraduationUserFacadeTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public void init() {
3535
FakeUserRepository fakeUserRepository = new FakeUserRepository();
3636

3737
GraduationUserQueryService graduationUserQueryService = new GraduationUserQueryService(fakeGraduationUserRepository,new FakeThesisRepository(), new FakeCertificateRepository(), new GraduationUserExcelImpl());
38-
GraduationUserCommandService graduationUserCommandService = new GraduationUserCommandService(fakeGraduationUserRepository, fakeUserRepository);
38+
GraduationUserCommandService graduationUserCommandService = new GraduationUserCommandService(fakeGraduationUserRepository);
3939

4040
UserQueryService userQueryService = new UserQueryService(fakeUserRepository);
4141
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

aics-domain/src/main/java/kgu/developers/domain/certificate/application/query/CertificateQueryService.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@
1111
public class CertificateQueryService {
1212
private final CertificateRepository certificateRepository;
1313

14-
public boolean isApproved(Long id) {
15-
return certificateRepository.findApprovalByIdAndDeletedAtIsNull(id)
16-
.orElseThrow(CertificateNotFoundException::new);
17-
}
1814
public Certificate getById(Long id) {
1915
return certificateRepository.findByIdAndDeletedAtIsNull(id)
2016
.orElseThrow(CertificateNotFoundException::new);

aics-domain/src/main/java/kgu/developers/domain/graduationUser/application/command/GraduationUserCommandService.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
import kgu.developers.domain.graduationUser.domain.GraduationUserRepository;
66
import kgu.developers.domain.graduationUser.exception.GraduationUserIdDuplicateException;
77
import kgu.developers.domain.schedule.domain.Schedule;
8-
import kgu.developers.domain.user.domain.UserRepository;
9-
import kgu.developers.domain.user.exception.UserNotFoundException;
108
import lombok.RequiredArgsConstructor;
119
import org.springframework.stereotype.Service;
1210
import org.springframework.transaction.annotation.Transactional;
@@ -18,7 +16,6 @@
1816
@RequiredArgsConstructor
1917
public class GraduationUserCommandService {
2018
private final GraduationUserRepository graduationUserRepository;
21-
private final UserRepository userRepository;
2219

2320
public Long createGraduationUser(String studentId, String name, String advisor, Boolean capstoneCompletion, String department, YearMonth graduationDate) {
2421
validateId(studentId);
@@ -29,8 +26,6 @@ public Long createGraduationUser(String studentId, String name, String advisor,
2926
private void validateId(String id) {
3027
if (graduationUserRepository.findByUserIdAndDeletedAtIsNull(id).isPresent())
3128
throw new GraduationUserIdDuplicateException();
32-
if(userRepository.findById(id).isEmpty())
33-
throw new UserNotFoundException();
3429
}
3530

3631
public void updateGraduationType(GraduationUser graduationUser, GraduationType type) {

0 commit comments

Comments
 (0)