diff --git a/src/docs/asciidoc/api/application/application.adoc b/src/docs/asciidoc/api/application/application.adoc index 7a3acc8..47c5f3e 100644 --- a/src/docs/asciidoc/api/application/application.adoc +++ b/src/docs/asciidoc/api/application/application.adoc @@ -55,3 +55,20 @@ include::{snippets}/admin-application-updateDocumentPass-doc/request-fields.adoc ==== HTTP Request include::{snippets}/admin-application-updateInterviewTime-doc/http-request.adoc[] include::{snippets}/admin-application-updateInterviewTime-doc/request-fields.adoc[] + + +=== 서류 합격 메일 +==== HTTP Request +include::{snippets}/admin-application-sendDocumentPassEmail-doc/http-request.adoc[] + +=== 서류 불합격 메일 +==== HTTP Request +include::{snippets}/admin-application-sendDocumentFailEmail-doc/http-request.adoc[] + +=== 최종 합격 메일 +==== HTTP Request +include::{snippets}/admin-application-sendFinalPassEmail-doc/http-request.adoc[] + +=== 최종 불합격 메일 +==== HTTP Request +include::{snippets}/admin-application-sendFinalFailEmail-doc/http-request.adoc[] \ No newline at end of file diff --git a/src/main/java/yonseigolf/server/apply/controller/ApplicationController.java b/src/main/java/yonseigolf/server/apply/controller/ApplicationController.java index 4699ac8..a602eab 100644 --- a/src/main/java/yonseigolf/server/apply/controller/ApplicationController.java +++ b/src/main/java/yonseigolf/server/apply/controller/ApplicationController.java @@ -155,4 +155,60 @@ public ResponseEntity updateInterviewTime(@PathVariable Long id, "연세골프 지원서 면접 시간 수정 성공" )); } + + @PostMapping("/admin/forms/documentPassEmail") + public ResponseEntity sendDocumentPassEmail() { + + applicationService.sendDocumentPassEmail(); + + return ResponseEntity + .ok() + .body(new CustomResponse( + "success", + 200, + "연세골프 지원서 서류 합격자 이메일 전송 성공" + )); + } + + @PostMapping("/admin/forms/finalPassEmail") + public ResponseEntity sendFinalPassEmail() { + + applicationService.sendFinalPassEmail(); + + return ResponseEntity + .ok() + .body(new CustomResponse( + "success", + 200, + "연세골프 지원서 최종 합격자 이메일 전송 성공" + )); + } + + @PostMapping("/admin/forms/documentFailEmail") + public ResponseEntity sendDocumentFailEmail() { + + applicationService.sendDocumentFailEmail(); + + return ResponseEntity + .ok() + .body(new CustomResponse( + "success", + 200, + "연세골프 지원서 서류 불합격자 이메일 전송 성공" + )); + } + + @PostMapping("/admin/forms/finalFailEmail") + public ResponseEntity sendFinalFailEmail() { + + applicationService.sendFinalFailEmail(); + + return ResponseEntity + .ok() + .body(new CustomResponse( + "success", + 200, + "연세골프 지원서 최종 불합격자 이메일 전송 성공" + )); + } } diff --git a/src/main/java/yonseigolf/server/apply/repository/ApplicationRepositoryCustom.java b/src/main/java/yonseigolf/server/apply/repository/ApplicationRepositoryCustom.java index bc007fe..69f2b84 100644 --- a/src/main/java/yonseigolf/server/apply/repository/ApplicationRepositoryCustom.java +++ b/src/main/java/yonseigolf/server/apply/repository/ApplicationRepositoryCustom.java @@ -3,10 +3,13 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import yonseigolf.server.apply.dto.response.SingleApplicationResult; +import yonseigolf.server.apply.entity.Application; import java.util.List; public interface ApplicationRepositoryCustom { Page getApplicationResults(Boolean documentPass, Boolean finalPass, Pageable pageable); + + List findApplicationsForEmail(Boolean documentPass, Boolean finalPass); } diff --git a/src/main/java/yonseigolf/server/apply/repository/ApplicationRepositoryImpl.java b/src/main/java/yonseigolf/server/apply/repository/ApplicationRepositoryImpl.java index 80b75b9..d62bfce 100644 --- a/src/main/java/yonseigolf/server/apply/repository/ApplicationRepositoryImpl.java +++ b/src/main/java/yonseigolf/server/apply/repository/ApplicationRepositoryImpl.java @@ -9,6 +9,7 @@ import org.springframework.data.domain.Pageable; import yonseigolf.server.apply.dto.response.QSingleApplicationResult; import yonseigolf.server.apply.dto.response.SingleApplicationResult; +import yonseigolf.server.apply.entity.Application; import java.util.List; @@ -47,6 +48,17 @@ public Page getApplicationResults(Boolean documentPass, return new PageImpl<>(results, pageable, total); } + @Override + public List findApplicationsForEmail(Boolean documentPass, Boolean finalPass) { + + return queryFactory.selectFrom(application) + .where( + documentPassEq(documentPass), + finalPassEq(finalPass) + ) + .fetch(); + } + private BooleanExpression documentPassEq(Boolean documentPass) { if (documentPass == null) { diff --git a/src/main/java/yonseigolf/server/apply/service/ApplyService.java b/src/main/java/yonseigolf/server/apply/service/ApplyService.java index 5061ccc..13da315 100644 --- a/src/main/java/yonseigolf/server/apply/service/ApplyService.java +++ b/src/main/java/yonseigolf/server/apply/service/ApplyService.java @@ -13,8 +13,10 @@ import yonseigolf.server.apply.entity.EmailAlarm; import yonseigolf.server.apply.repository.ApplicationRepository; import yonseigolf.server.apply.repository.EmailRepository; +import yonseigolf.server.email.service.EmailService; import java.time.LocalDateTime; +import java.util.List; @Service @@ -22,12 +24,14 @@ public class ApplyService { private final ApplicationRepository applicationRepository; private final EmailRepository emailRepository; + private final EmailService emailService; @Autowired - public ApplyService(ApplicationRepository applicationRepository, EmailRepository emailRepository) { + public ApplyService(ApplicationRepository applicationRepository, EmailRepository emailRepository, EmailService emailService) { this.applicationRepository = applicationRepository; this.emailRepository = emailRepository; + this.emailService = emailService; } public void apply(ApplicationRequest request) { @@ -68,6 +72,65 @@ public void updateInterviewTime(Long id, LocalDateTime time) { findById(id).updateInterviewTime(time); } + + // TODO: ENUM 활용해서 코드 개선 가능할듯 보인다 + public void sendDocumentPassEmail() { + List applications = findApplicationsByPassFail(true, null); + + applications.stream() + .forEach(application -> emailService.sendEmail(application.getEmail(), + "안녕하세요. 연세대학교 골프동아리 결과 메일입니다.", + application.getName() +"님 서류 합격 축하드립니다. \n" + + "면접 일정은 추후 공지될 예정입니다. \n" + + "감사합니다.")); + } + + public void sendFinalPassEmail() { + List applications = findApplicationsByPassFail(true, true); + + applications.stream() + .forEach(application -> emailService.sendEmail(application.getEmail(), + "안녕하세요. 연세대학교 골프동아리 결과 메일입니다.", + application.getName() +"님 최종 합격 축하드립니다. \n" + + "추후 일정은 문자로 공지될 예정입니다. \n" + + "감사합니다.")); + } + + public void sendDocumentFailEmail() { + List applications = findApplicationsByPassFail(false, null); + + applications.stream() + .forEach(application -> emailService.sendEmail(application.getEmail(), + "안녕하세요. 연세대학교 골프동아리 결과 메일입니다.", + application.getName() + "님 연세골프에 지원해주셔서 감사합니다. \n\n\n" + + "안타깝게도 " + application.getName() + "님께 이번 연골 모집에서 합격의 소식을 전해드리지 못하게 되었습니다." + + application.getName() + "님의 뛰어난 열정에도 불구하고, 연세골프는 한정된 인원으로만 운영되는 만큼 아쉽게도 이런 소식을 전해드리게 됐습니다." + + "비록 이번 모집에서 " + application.getName() +"님과 함께하지 못하지만, 다음에 함께 할 수 있기를 바라겠습니다. \n\n" + + "바쁘신 와중에 지원해주셔서 감사합니다. \n\n" + + "연세 골프 운영진 드림") + ); + } + + public void sendFinalFailEmail() { + List applications = findApplicationsByPassFail(true, false); + + applications.stream() + .forEach(application -> emailService.sendEmail(application.getEmail(), + "안녕하세요. 연세대학교 골프동아리 결과 메일입니다.", + application.getName() + "님 연세골프에 지원해주셔서 감사합니다. \n\n\n" + + "안타깝게도 " + application.getName() + "님께 이번 연골 모집에서 합격의 소식을 전해드리지 못하게 되었습니다." + + application.getName() + "님의 뛰어난 열정에도 불구하고, 연세골프는 한정된 인원으로만 운영되는 만큼 아쉽게도 이런 소식을 전해드리게 됐습니다." + + "비록 이번 모집에서 " + application.getName() +"님과 함께하지 못하지만, 다음에 함께 할 수 있기를 바라겠습니다. \n\n" + + "바쁘신 와중에 지원해주셔서 감사합니다. \n\n" + + "연세 골프 운영진 드림") + ); + } + + private List findApplicationsByPassFail(Boolean docuemntPass, Boolean finalPass) { + + return applicationRepository.findApplicationsForEmail(docuemntPass, finalPass); + } + private Application findById(Long id) { return applicationRepository.findById(id) diff --git a/src/main/java/yonseigolf/server/email/service/EmailService.java b/src/main/java/yonseigolf/server/email/service/EmailService.java index b8dfef9..3c9af6f 100644 --- a/src/main/java/yonseigolf/server/email/service/EmailService.java +++ b/src/main/java/yonseigolf/server/email/service/EmailService.java @@ -38,12 +38,13 @@ public void sendApplyStartAlert() { emailRepository.deleteAll(); } + private List findAllAlert() { return emailRepository.findAll(); } - private void sendEmail(String to, String subject, String text) { + public void sendEmail(String to, String subject, String text) { SimpleMailMessage message = new SimpleMailMessage(); message.setTo(to); diff --git a/src/test/java/yonseigolf/server/apply/controller/ApplicationControllerTest.java b/src/test/java/yonseigolf/server/apply/controller/ApplicationControllerTest.java index 5c3778e..dba8620 100644 --- a/src/test/java/yonseigolf/server/apply/controller/ApplicationControllerTest.java +++ b/src/test/java/yonseigolf/server/apply/controller/ApplicationControllerTest.java @@ -464,4 +464,80 @@ void updateInterviewTimeTest() throws Exception { ) ); } + + @Test + @DisplayName("서류 합격자들에게 합격 이메일을 전송할 수 있다.") + void sendDocumentPassEmailTest() throws Exception { + // given + doNothing().when(applyService).sendDocumentPassEmail(); + + // when + applyService.sendDocumentPassEmail(); + + // then + mockMvc.perform(post("/admin/forms/documentPassEmail")) + .andExpect(status().isOk()) + .andDo(print()) + .andDo(document("admin-application-sendDocumentPassEmail-doc", + getDocumentRequest(), + getDocumentResponse() + )); + } + + @Test + @DisplayName("서류 불합격자들에게 불합격 이메일을 전송할 수 있다.") + void sendDocumentFailEmailTest() throws Exception { + // given + doNothing().when(applyService).sendDocumentFailEmail(); + + // when + applyService.sendDocumentFailEmail(); + + // then + mockMvc.perform(post("/admin/forms/documentFailEmail")) + .andExpect(status().isOk()) + .andDo(print()) + .andDo(document("admin-application-sendDocumentFailEmail-doc", + getDocumentRequest(), + getDocumentResponse() + )); + } + + @Test + @DisplayName("최종 합격자들에게 합격 이메일을 전송할 수 있다.") + void sendFinalPassEmailTest() throws Exception { + // given + doNothing().when(applyService).sendFinalPassEmail(); + + // when + applyService.sendFinalPassEmail(); + + // then + mockMvc.perform(post("/admin/forms/finalPassEmail")) + .andExpect(status().isOk()) + .andDo(print()) + .andDo(document("admin-application-sendFinalPassEmail-doc", + getDocumentRequest(), + getDocumentResponse() + )); + } + + @Test + @DisplayName("최종 불합격자들에게 불합격 이메일을 전송할 수 있다.") + void sendFinalFailEmailTest() throws Exception { + // given + doNothing().when(applyService).sendFinalFailEmail(); + + // when + applyService.sendFinalFailEmail(); + + // then + mockMvc.perform(post("/admin/forms/finalPassEmail")) + .andExpect(status().isOk()) + .andDo(print()) + .andDo(document("admin-application-sendFinalFailEmail-doc", + getDocumentRequest(), + getDocumentResponse() + )); + } }