Skip to content

Commit 3231219

Browse files
authored
feat/KD-74: 논문 및 자격증 제출의 개별적 승인 및 반려 API 구현 (#333)
* feat: 제출 단일 승인과 승인 취소 API 구현 * feat: 제출 단일 승인과 승인 취소 API 테스트 코드 추가 * fix: 오타 수정 * feat: 코드래빗 리뷰 반영
1 parent d2a862b commit 3231219

File tree

7 files changed

+187
-7
lines changed

7 files changed

+187
-7
lines changed

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import kgu.developers.domain.graduationUser.application.query.GraduationUserQueryService;
2424
import kgu.developers.domain.graduationUser.domain.GraduationType;
2525
import kgu.developers.domain.graduationUser.domain.GraduationUser;
26+
import kgu.developers.domain.graduationUser.exception.GraduationTypeNotSelectedException;
27+
import kgu.developers.domain.graduationUser.exception.GraudationUserSubmissionMismatchException;
2628
import kgu.developers.domain.thesis.application.command.ThesisCommandService;
2729
import kgu.developers.domain.thesis.application.query.ThesisQueryService;
2830
import kgu.developers.domain.thesis.domain.Thesis;
@@ -224,4 +226,36 @@ public GraduationUserBatchDisapproveResponse disapproveGraduationUsers(Graduatio
224226

225227
return GraduationUserBatchDisapproveResponse.from(disapprovedUserIds);
226228
}
229+
230+
public Long approveSubmission(Long graduationUserId, Long submissionId) {
231+
GraduationUser graduationUser = graduationUserQueryService.getById(graduationUserId);
232+
validateSubmissionOwner(graduationUser, submissionId);
233+
if(graduationUser.getGraduationType() == GraduationType.CERTIFICATE) {
234+
certificateCommandService.approve(submissionId);
235+
} else if(graduationUser.getGraduationType() == GraduationType.THESIS) {
236+
thesisCommandService.approve(submissionId);
237+
}
238+
return graduationUserId;
239+
}
240+
241+
public Long disapproveSubmission(Long graduationUserId, Long submissionId) {
242+
GraduationUser graduationUser = graduationUserQueryService.getById(graduationUserId);
243+
validateSubmissionOwner(graduationUser, submissionId);
244+
if(graduationUser.getGraduationType() == GraduationType.CERTIFICATE) {
245+
certificateCommandService.disapprove(submissionId);
246+
} else if(graduationUser.getGraduationType() == GraduationType.THESIS) {
247+
thesisCommandService.disapprove(submissionId);
248+
}
249+
return graduationUserId;
250+
}
251+
252+
private void validateSubmissionOwner(GraduationUser graduationUser, Long submissionId) {
253+
if(graduationUser.getGraduationType() == GraduationType.CERTIFICATE) {
254+
if(graduationUser.getCertificateId() != submissionId) throw new GraudationUserSubmissionMismatchException();
255+
} else if(graduationUser.getGraduationType() == GraduationType.THESIS) {
256+
if(graduationUser.getMidThesisId() != submissionId && graduationUser.getFinalThesisId() != submissionId) throw new GraudationUserSubmissionMismatchException();
257+
} else {
258+
throw new GraduationTypeNotSelectedException();
259+
}
260+
}
227261
}

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,45 @@ ResponseEntity<GraduationUserBatchDisapproveResponse> disapproveGraduationUsers(
162162
required = true
163163
) @Valid @RequestBody GraduationUserBatchDisapproveRequest request
164164
);
165+
166+
@Operation(summary = "제출 단일 승인 API", description = """
167+
- Description : 이 API는 선택한 졸업 대상자의 특정 논문/자격증을 승인합니다.
168+
- Assignee : 장영후
169+
""")
170+
@ApiResponse(
171+
responseCode = "200",
172+
content = @Content(schema = @Schema(implementation = GraduationUserPersistResponse.class))
173+
)
174+
ResponseEntity<GraduationUserPersistResponse> approveSubmission(
175+
@Parameter(
176+
description = "졸업 대상자 ID는 URL 경로 변수 입니다.",
177+
example = "1",
178+
required = true
179+
) @Positive @PathVariable Long graduationUserId,
180+
@Parameter(
181+
description = "논문/자격증 ID는 URL 경로 변수 입니다.",
182+
example = "1",
183+
required = true
184+
) @Positive @PathVariable Long submissionId
185+
);
186+
187+
@Operation(summary = "제출 승인 취소 API", description = """
188+
- Description : 이 API는 선택한 졸업 대상자의 특정 논문/자격증을 승인 취소합니다.
189+
- Assignee : 장영후
190+
""")
191+
@ApiResponse(
192+
responseCode = "200",
193+
content = @Content(schema = @Schema(implementation = GraduationUserPersistResponse.class)))
194+
ResponseEntity<GraduationUserPersistResponse> disapproveSubmission(
195+
@Parameter(
196+
description = "졸업 대상자 ID는 URL 경로 변수 입니다.",
197+
example = "1",
198+
required = true
199+
) @Positive @PathVariable Long graduationUserId,
200+
@Parameter(
201+
description = "논문/자격증 ID는 URL 경로 변수 입니다.",
202+
example = "1",
203+
required = true
204+
) @Positive @PathVariable Long submissionId
205+
);
165206
}

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,24 @@ public ResponseEntity<GraduationUserBatchDisapproveResponse> disapproveGraduatio
135135
GraduationUserBatchDisapproveResponse response = graduationUserAdminFacade.disapproveGraduationUsers(request);
136136
return ResponseEntity.ok(response);
137137
}
138+
139+
@Override
140+
@PatchMapping("/approve/{graduationUserId}/{submissionId}")
141+
public ResponseEntity<GraduationUserPersistResponse> approveSubmission(
142+
@Positive @PathVariable Long graduationUserId,
143+
@Positive @PathVariable Long submissionId
144+
) {
145+
Long approvedGraduationuserId = graduationUserAdminFacade.approveSubmission(graduationUserId,submissionId);
146+
return ResponseEntity.ok(GraduationUserPersistResponse.of(approvedGraduationuserId));
147+
}
148+
149+
@Override
150+
@PatchMapping("/disapprove/{graduationUserId}/{submissionId}")
151+
public ResponseEntity<GraduationUserPersistResponse> disapproveSubmission(
152+
@Positive @PathVariable Long graduationUserId,
153+
@Positive @PathVariable Long submissionId
154+
) {
155+
Long disapprovedGraduationuserId = graduationUserAdminFacade.disapproveSubmission(graduationUserId,submissionId);
156+
return ResponseEntity.ok(GraduationUserPersistResponse.of(disapprovedGraduationuserId));
157+
}
138158
}

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

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -319,10 +319,10 @@ public void approveGraduationUsers_Success() {
319319
@DisplayName("disapproveGraduationUsers는 여러 GraduationUser의 제출 승인을 취소한다.")
320320
public void disapproveGraduationUsers_Success() {
321321
// given
322-
// 먼저 승인된 상태로 만듦
323-
fakeCertificateRepository.save(Certificate.of(1L, 1L, 1L, true, null, null, null));
324-
fakeThesisRepository.save(Thesis.of(1L, 1L, 1L, true, null, null, null));
325-
fakeThesisRepository.save(Thesis.of(2L, 1L, 2L, true, null, null, null));
322+
GraduationUserBatchApproveRequest approveRequest = GraduationUserBatchApproveRequest.builder()
323+
.ids(Arrays.asList(1L, 2L))
324+
.build();
325+
graduationUserAdminFacade.approveGraduationUsers(approveRequest);
326326

327327
List<Long> graduationUserIds = Arrays.asList(1L, 2L);
328328
GraduationUserBatchDisapproveRequest request = GraduationUserBatchDisapproveRequest.builder()
@@ -343,9 +343,6 @@ public void disapproveGraduationUsers_Success() {
343343
@DisplayName("disapproveGraduationUsers는 이미 승인이 취소된 유저는 결과 목록에 포함하지 않는다.")
344344
public void disapproveGraduationUsers_AlreadyDisapproved() {
345345
// given
346-
// 이미 승인 취소 상태로 만듦
347-
fakeCertificateRepository.save(Certificate.of(1L, 1L, 1L, false, null, null, null));
348-
349346
List<Long> graduationUserIds = List.of(1L);
350347
GraduationUserBatchDisapproveRequest request = GraduationUserBatchDisapproveRequest.builder()
351348
.ids(graduationUserIds)
@@ -375,4 +372,68 @@ public void disapproveGraduationUsers_NoSubmission() {
375372
// then
376373
assertEquals(0, response.disapprovedIds().size());
377374
}
375+
376+
@Test
377+
@DisplayName("approveSubmission은 자격증 타입 GraduationUser의 자격증 제출을 단일 승인한다.")
378+
public void approveSubmission_CertificateType_Success() {
379+
// given
380+
Long graduationUserId = 1L;
381+
Long submissionId = 1L; // certificateId
382+
383+
// when
384+
Long result = graduationUserAdminFacade.approveSubmission(graduationUserId, submissionId);
385+
386+
// then
387+
assertEquals(graduationUserId, result);
388+
assertEquals(true, fakeCertificateRepository.findApprovalByIdAndDeletedAtIsNull(1L).get());
389+
}
390+
391+
@Test
392+
@DisplayName("approveSubmission은 논문 타입 GraduationUser의 논문 제출을 단일 승인한다.")
393+
public void approveSubmission_ThesisType_Success() {
394+
// given
395+
Long graduationUserId = 2L;
396+
Long submissionId = 1L; // midThesisId
397+
398+
// when
399+
Long result = graduationUserAdminFacade.approveSubmission(graduationUserId, submissionId);
400+
401+
// then
402+
assertEquals(graduationUserId, result);
403+
assertEquals(true, fakeThesisRepository.findApprovalByIdAndDeletedAtIsNull(1L).get());
404+
assertEquals(false, fakeThesisRepository.findApprovalByIdAndDeletedAtIsNull(2L).get());
405+
}
406+
407+
@Test
408+
@DisplayName("disapproveSubmission은 자격증 타입 GraduationUser의 자격증 제출 승인을 단일 취소한다.")
409+
public void disapproveSubmission_CertificateType_Success() {
410+
// given
411+
Long graduationUserId = 1L;
412+
Long submissionId = 1L; // certificateId
413+
graduationUserAdminFacade.approveSubmission(graduationUserId, submissionId);
414+
415+
// when
416+
Long result = graduationUserAdminFacade.disapproveSubmission(graduationUserId, submissionId);
417+
418+
// then
419+
assertEquals(graduationUserId, result);
420+
assertEquals(false, fakeCertificateRepository.findApprovalByIdAndDeletedAtIsNull(1L).get());
421+
}
422+
423+
@Test
424+
@DisplayName("disapproveSubmission은 논문 타입 GraduationUser의 논문 제출 승인을 단일 취소한다.")
425+
public void disapproveSubmission_ThesisType_Success() {
426+
// given
427+
Long graduationUserId = 2L;
428+
Long submissionId = 2L; // finalThesisId
429+
graduationUserAdminFacade.approveSubmission(graduationUserId, submissionId);
430+
431+
// when
432+
Long result = graduationUserAdminFacade.disapproveSubmission(graduationUserId, submissionId);
433+
434+
// then
435+
assertEquals(graduationUserId, result);
436+
assertEquals(false, fakeThesisRepository.findApprovalByIdAndDeletedAtIsNull(2L).get());
437+
assertEquals(false, fakeThesisRepository.findApprovalByIdAndDeletedAtIsNull(1L).get());
438+
}
378439
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package kgu.developers.domain.graduationUser.exception;
2+
3+
import kgu.developers.common.exception.CustomException;
4+
5+
import static kgu.developers.domain.graduationUser.exception.GraduationUserDomainExceptionCode.GRADUATION_TYPE_NOT_SELECTED;
6+
7+
public class GraduationTypeNotSelectedException extends CustomException {
8+
public GraduationTypeNotSelectedException() {
9+
super(GRADUATION_TYPE_NOT_SELECTED);
10+
}
11+
}

aics-domain/src/main/java/kgu/developers/domain/graduationUser/exception/GraduationUserDomainExceptionCode.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ public enum GraduationUserDomainExceptionCode implements ExceptionCode {
1919
GRADUATION_USER_ID_DUPLICATED(CONFLICT, "이미 동일한 학번의 졸업 대상자 정보가 존재합니다."),
2020
GRADUATION_USER_EXCEL_GENERATION_FAILED(INTERNAL_SERVER_ERROR, "졸업 대상자 엑셀 파일의 생성 중 오류가 발생했습니다."),
2121
GRADUATION_TYPE_SUBMISSION_PERIOD_CLOSED(BAD_REQUEST, "현재 졸업 방식을 제출하는 기간이 아닙니다."),
22+
GRADUATION_TYPE_NOT_SELECTED(NOT_FOUND, "해당 졸업 대상자는 졸업 방식을 선택하지 않았습니다."),
23+
GRADUATION_USER_SUBMISSION_MISMATCH(BAD_REQUEST, "해당 제출물은 해당 졸업 대상자가 제출하지 않았습니다."),
2224
;
2325

2426
private final HttpStatus status;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package kgu.developers.domain.graduationUser.exception;
2+
3+
import kgu.developers.common.exception.CustomException;
4+
5+
import static kgu.developers.domain.graduationUser.exception.GraduationUserDomainExceptionCode.GRADUATION_USER_SUBMISSION_MISMATCH;
6+
7+
public class GraudationUserSubmissionMismatchException extends CustomException {
8+
public GraudationUserSubmissionMismatchException() {
9+
super(GRADUATION_USER_SUBMISSION_MISMATCH);
10+
}
11+
}

0 commit comments

Comments
 (0)