Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
import kgu.developers.common.response.PaginatedListResponse;
import kgu.developers.domain.certificate.application.command.CertificateCommandService;
import kgu.developers.domain.certificate.application.query.CertificateQueryService;
import kgu.developers.domain.certificate.domain.Certificate;
import kgu.developers.domain.graduationUser.application.command.GraduationUserCommandService;
import kgu.developers.domain.graduationUser.application.query.GraduationUserQueryService;
import kgu.developers.domain.graduationUser.domain.GraduationType;
import kgu.developers.domain.graduationUser.domain.GraduationUser;
import kgu.developers.domain.thesis.application.command.ThesisCommandService;
import kgu.developers.domain.thesis.application.query.ThesisQueryService;
import kgu.developers.domain.thesis.domain.Thesis;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
Expand Down Expand Up @@ -90,36 +92,37 @@ private GraduationUserStatusResponse buildSubmissionStatus(GraduationUser user)
}

private GraduationUserStatusResponse.Certificate buildCertificateStatus(Long certificateId) {
boolean submitted = certificateId != null;
boolean approval = false;
if(submitted) {
approval = certificateQueryService.isApproved(certificateId);
if (certificateId == null) {
return GraduationUserStatusResponse.Certificate.of(GraduationType.CERTIFICATE,false,false,null);
}

return new GraduationUserStatusResponse.Certificate("CERTIFICATE", submitted, approval);
Certificate certificate = certificateQueryService.getById(certificateId);

return GraduationUserStatusResponse.Certificate.of(GraduationType.CERTIFICATE, true, certificate.isApproved(), certificate.getCreatedAt());
}

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

boolean midThesisSubmitted = middleThesisId != null;
boolean midThesisapproval = false;
if(midThesisSubmitted) {
midThesisapproval = thesisQueryService.isApproved(middleThesisId);
}
GraduationUserStatusResponse.Thesis.Middle midThesisStatus;
GraduationUserStatusResponse.Thesis.Final finalThesisStatus;

GraduationUserStatusResponse.Thesis.Middle midStatus =
new GraduationUserStatusResponse.Thesis.Middle(midThesisSubmitted,midThesisapproval);
if(middleThesisId == null) {
midThesisStatus = GraduationUserStatusResponse.Thesis.Middle.of(false, false, null);
} else {
Thesis midThesis = thesisQueryService.getById(middleThesisId);

boolean finalThesisSubmitted = finalThesisId != null;
boolean finalThesisapproval = false;
if(finalThesisSubmitted) {
finalThesisapproval = thesisQueryService.isApproved(finalThesisId);
midThesisStatus = GraduationUserStatusResponse.Thesis.Middle.of(true, midThesis.isApproved(), midThesis.getCreatedAt());
}

GraduationUserStatusResponse.Thesis.Final finalStatus =
new GraduationUserStatusResponse.Thesis.Final(finalThesisSubmitted,finalThesisapproval);
if(finalThesisId == null) {
finalThesisStatus = GraduationUserStatusResponse.Thesis.Final.of(false, false, null);
} else {
Thesis midThesis = thesisQueryService.getById(middleThesisId);

finalThesisStatus = GraduationUserStatusResponse.Thesis.Final.of(true, midThesis.isApproved(), midThesis.getCreatedAt());
}

return new GraduationUserStatusResponse.Thesis("THESIS", midStatus, finalStatus);
return GraduationUserStatusResponse.Thesis.of(GraduationType.THESIS, midThesisStatus, finalThesisStatus);
}

public void deleteGraduationUser(Long id) {
Expand All @@ -128,7 +131,9 @@ public void deleteGraduationUser(Long id) {
}

public GraduationUserDetailResponse getGraduationUserById(Long graduationUserId) {
return GraduationUserDetailResponse.from(graduationUserQueryService.getById(graduationUserId));
GraduationUser graduationUser = graduationUserQueryService.getById(graduationUserId);
GraduationUserStatusResponse status = buildSubmissionStatus(graduationUser);
return GraduationUserDetailResponse.from(graduationUser, status);
}

public GraduationUserBatchDeleteResponse deleteGraduationUsers(GraduationUserBatchDeleteRequest request) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,30 @@ public record GraduationUserDetailResponse(
String major,

@Schema(description = "캡스톤 이수 여부", example = "true", requiredMode = REQUIRED)
Boolean capstoneCompletion
Boolean capstoneCompletion,

@Schema(
description = "졸업 요건 제출 및 승인 상태 (자격증 또는 논문)",
example = "{"
+ "\"type\": \"THESIS\", "
+ "\"midThesis\": {"
+ "\"submitted\": true, "
+ "\"approval\": true, "
+ "\"createdAt\": \"2024-08-01\" "
+ "}, "
+ "\"finalThesis\": {"
+ "\"submitted\": false, "
+ "\"approval\": false, "
+ "\"createdAt\": \"null\" "
+ "}"
+ "}",
requiredMode = REQUIRED
)
GraduationUserStatusResponse status
) {
public static GraduationUserDetailResponse from(
GraduationUser graduationUser
GraduationUser graduationUser,
GraduationUserStatusResponse status
) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
return GraduationUserDetailResponse.builder()
Expand All @@ -45,6 +65,7 @@ public static GraduationUserDetailResponse from(
.advisor(graduationUser.getAdvisorProfessor())
.major(graduationUser.getDepartment())
.capstoneCompletion(graduationUser.getCapstoneCompletion())
.status(status)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
package kgu.developers.admin.graduationUser.presentation.response;

import io.swagger.v3.oas.annotations.media.Schema;
import kgu.developers.domain.graduationUser.domain.GraduationType;
import lombok.Builder;
import org.springframework.format.annotation.DateTimeFormat;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;

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

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

@Schema(description = "승인 여부", example = "false")
boolean approval
boolean approval,

@Schema(description = "제출일", example = "2024-08-11", requiredMode = REQUIRED)
@DateTimeFormat(pattern = "yyyy-MM-dd")
String createdAt

) implements GraduationUserStatusResponse {
public static Certificate of(GraduationType type, boolean submitted, boolean approval, LocalDateTime createdAt) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
return Certificate.builder()
.type(type.name())
.submitted(submitted)
.approval(approval)
.createdAt(createdAt.format(formatter))
.build();
}
}

@Builder
@Schema(description = "논문 제출 상태")
record Thesis(
@Schema(description = "졸업 타입", example = "THESIS")
Expand All @@ -35,23 +59,58 @@ record Thesis(
@Schema(description = "최종 논문 상태")
Final finalThesis
) implements GraduationUserStatusResponse {
public static Thesis of(GraduationType type, Middle midThesis, Final finalThesis) {
return Thesis.builder()
.type(type.name())
.midThesis(midThesis)
.finalThesis(finalThesis)
.build();
}

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

@Schema(description = "승인 여부", example = "true")
boolean approval
) {}
boolean approval,

@Schema(description = "제출일", example = "2024-08-11", requiredMode = REQUIRED)
@DateTimeFormat(pattern = "yyyy-MM-dd")
String createdAt
) {
public static Middle of(boolean submitted, boolean approval, LocalDateTime createdAt) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
return Middle.builder()
.submitted(submitted)
.approval(approval)
.createdAt(createdAt.format(formatter))
.build();
}
}

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

@Schema(description = "승인 여부", example = "false")
boolean approval
) {}
boolean approval,

@Schema(description = "제출일", example = "2024-08-11", requiredMode = REQUIRED)
@DateTimeFormat(pattern = "yyyy-MM-dd")
String createdAt
) {
public static Final of(boolean submitted, boolean approval, LocalDateTime createdAt) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
return Final.builder()
.submitted(submitted)
.approval(approval)
.createdAt(createdAt.format(formatter))
.build();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,23 @@ public record GraduationUserSummaryResponse(
+ "\"type\": \"THESIS\", "
+ "\"midThesis\": {"
+ "\"submitted\": true, "
+ "\"approval\": true"
+ "\"approval\": true, "
+ "\"createdAt\": \"2024-08-01\" "
+ "}, "
+ "\"finalThesis\": {"
+ "\"submitted\": false, "
+ "\"approval\": false"
+ "\"approval\": false, "
+ "\"createdAt\": \"null\" "
+ "}"
+ "}",
requiredMode = REQUIRED
)
GraduationUserStatusResponse status
) {
public static GraduationUserSummaryResponse of(GraduationUser graduationUser, GraduationUserStatusResponse status) {
public static GraduationUserSummaryResponse of(
GraduationUser graduationUser,
GraduationUserStatusResponse status
) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");

return GraduationUserSummaryResponse.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public class GraduationUserAdminFacadeTest {
public void init() {
FakeGraduationUserRepository fakeGraduationUserRepository = new FakeGraduationUserRepository();
fakeUserRepository = new FakeUserRepository();
GraduationUserCommandService graduationUserCommandService = new GraduationUserCommandService(fakeGraduationUserRepository, fakeUserRepository);
GraduationUserCommandService graduationUserCommandService = new GraduationUserCommandService(fakeGraduationUserRepository);

fakeThesisRepository = new FakeThesisRepository();
fakeCertificateRepository = new FakeCertificateRepository();
Expand Down
12 changes: 6 additions & 6 deletions aics-api/src/main/resources/db/data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,14 @@ VALUES ('참여 신청 방법을 자세히 알고 싶습니다.', '2025-03-03 00
('프로젝트 자료를 다운로드했습니다. 유익하네요.', '2025-03-03 07:01:00', '2025-03-03 07:01:00', 8, '202412347'),
('연구 참여 방법이 있나요?', '2025-03-03 07:02:00', '2025-03-03 07:02:00', 8, '202412346');

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

-- schedule
INSERT INTO schedule (submission_type, content, start_date, end_date, created_at, updated_at)
Expand Down
1 change: 1 addition & 0 deletions aics-api/src/main/resources/db/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ CREATE TABLE graduation_user
CONSTRAINT graduation_type_check
CHECK ((graduation_type)::TEXT = ANY (ARRAY ['THESIS', 'CERTIFICATE'])),
graduation_date DATE,
capstone_completion BOOLEAN,
mid_thesis_id BIGINT,
final_thesis_id BIGINT,
certificate_id BIGINT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public void init() {
FakeUserRepository fakeUserRepository = new FakeUserRepository();

GraduationUserQueryService graduationUserQueryService = new GraduationUserQueryService(fakeGraduationUserRepository,new FakeThesisRepository(), new FakeCertificateRepository(), new GraduationUserExcelImpl());
GraduationUserCommandService graduationUserCommandService = new GraduationUserCommandService(fakeGraduationUserRepository, fakeUserRepository);
GraduationUserCommandService graduationUserCommandService = new GraduationUserCommandService(fakeGraduationUserRepository);

UserQueryService userQueryService = new UserQueryService(fakeUserRepository);
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package kgu.developers.domain.certificate.application.query;

import kgu.developers.domain.certificate.domain.Certificate;
import kgu.developers.domain.certificate.domain.CertificateRepository;
import kgu.developers.domain.certificate.exception.CertificateNotFoundException;
import lombok.RequiredArgsConstructor;
Expand All @@ -10,8 +11,8 @@
public class CertificateQueryService {
private final CertificateRepository certificateRepository;

public boolean isApproved(Long id) {
return certificateRepository.findApprovalByIdAndDeletedAtIsNull(id)
.orElseThrow(CertificateNotFoundException::new);
public Certificate getById(Long id) {
return certificateRepository.findByIdAndDeletedAtIsNull(id)
.orElseThrow(CertificateNotFoundException::new);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import kgu.developers.domain.graduationUser.domain.GraduationUserRepository;
import kgu.developers.domain.graduationUser.exception.GraduationUserIdDuplicateException;
import kgu.developers.domain.schedule.domain.Schedule;
import kgu.developers.domain.user.domain.UserRepository;
import kgu.developers.domain.user.exception.UserNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -18,7 +16,6 @@
@RequiredArgsConstructor
public class GraduationUserCommandService {
private final GraduationUserRepository graduationUserRepository;
private final UserRepository userRepository;

public Long createGraduationUser(String studentId, String name, String advisor, Boolean capstoneCompletion, String department, YearMonth graduationDate) {
validateId(studentId);
Expand All @@ -29,8 +26,6 @@ public Long createGraduationUser(String studentId, String name, String advisor,
private void validateId(String id) {
if (graduationUserRepository.findByUserIdAndDeletedAtIsNull(id).isPresent())
throw new GraduationUserIdDuplicateException();
if(userRepository.findById(id).isEmpty())
throw new UserNotFoundException();
}

public void updateGraduationType(GraduationUser graduationUser, GraduationType type) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package kgu.developers.domain.thesis.application.query;

import kgu.developers.domain.thesis.domain.Thesis;
import kgu.developers.domain.thesis.domain.ThesisRepository;
import kgu.developers.domain.thesis.exception.ThesisNotFoundException;
import lombok.RequiredArgsConstructor;
Expand All @@ -10,8 +11,8 @@
public class ThesisQueryService {
private final ThesisRepository thesisRepository;

public boolean isApproved(Long id) {
return thesisRepository.findApprovalByIdAndDeletedAtIsNull(id)
.orElseThrow(ThesisNotFoundException::new);
public Thesis getById(Long id) {
return thesisRepository.findByIdAndDeletedAtIsNull(id)
.orElseThrow(ThesisNotFoundException::new);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public void init() {
private void initializeGraduationUserCommandService() {
fakeUserRepository = new FakeUserRepository();
fakeGraduationUserRepository = new FakeGraduationUserRepository();
graduationUserCommandService = new GraduationUserCommandService(fakeGraduationUserRepository, fakeUserRepository);
graduationUserCommandService = new GraduationUserCommandService(fakeGraduationUserRepository);
saveTestUser();
graduationUser = fakeGraduationUserRepository.save(saveTestGraduationuser());
}
Expand Down