diff --git a/src/docs/asciidoc/message.adoc b/src/docs/asciidoc/message.adoc index 31b50bef..60115de0 100644 --- a/src/docs/asciidoc/message.adoc +++ b/src/docs/asciidoc/message.adoc @@ -42,4 +42,26 @@ include::{snippets}/message-controller-test/마이스터전형과_마이스터 include::{snippets}/message-controller-test/마이스터전형에서_일반전형으로_바뀐_1차_합격자들에게_메시지를_보낸다/http-request.adoc[] ===== 마이스터전형 1차 합격자들에게 메시지를 보내는 경우 -include::{snippets}/message-controller-test/마이스터_전형_1차_합격자들에게_메시지를_보낸다/http-request.adoc[]https://xxx[] \ No newline at end of file +include::{snippets}/message-controller-test/마이스터_전형_1차_합격자들에게_메시지를_보낸다/http-request.adoc[]https://xxx[] + +=== 어드민을 제외한 모든 유저에게 메시지 보내기 +어드민을 제외한 모든 유저에게 메시지를 보낼 수 있습니다. + +==== 요청 형식 + +===== Request Header +include::{snippets}/message-controller-test/어드민을_제외한_전체_유저에게_메시지를_발송한다/request-headers.adoc[] + +===== Request Body +include::{snippets}/message-controller-test/어드민을_제외한_전체_유저에게_메시지를_발송한다/request-fields.adoc[] + +==== 요청 +include::{snippets}/message-controller-test/어드민을_제외한_전체_유저에게_메시지를_발송한다/http-request.adoc[] + +==== 응답 + +===== 정상 응답 +include::{snippets}/message-controller-test/어드민을_제외한_전체_유저에게_메시지를_발송한다/http-response.adoc[] + +===== 어드민을 제외한 유저가 아무도 없는 경우 +include::{snippets}/message-controller-test/어드민을_제외한_유저가_아무도_없으면_오류가_발생한다/http-response.adoc[] \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/application/message/SendMessageUseCase.java b/src/main/java/com/bamdoliro/maru/application/message/SendMessageUseCase.java index ef1db040..7e6f50a3 100644 --- a/src/main/java/com/bamdoliro/maru/application/message/SendMessageUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/message/SendMessageUseCase.java @@ -2,10 +2,14 @@ import com.bamdoliro.maru.domain.form.domain.Form; import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.domain.user.domain.User; +import com.bamdoliro.maru.domain.user.domain.type.Authority; import com.bamdoliro.maru.infrastructure.message.SendMessageService; import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.infrastructure.persistence.user.UserRepository; import com.bamdoliro.maru.presentation.message.dto.request.SendMessageByStatusRequest; import com.bamdoliro.maru.presentation.message.dto.request.SendMessageByTypeRequest; +import com.bamdoliro.maru.presentation.message.dto.request.SendMessageToAllUserRequest; import com.bamdoliro.maru.shared.annotation.UseCase; import lombok.RequiredArgsConstructor; @@ -17,6 +21,7 @@ public class SendMessageUseCase { private final FormRepository formRepository; private final SendMessageService sendMessageService; + private final UserRepository userRepository; public void execute(SendMessageByStatusRequest request) { List
formList = formRepository.findByStatus(request.getStatus()); @@ -32,22 +37,30 @@ public void execute(SendMessageByTypeRequest request) { sendMessageService.execute(phoneNumberList, request.getText(), request.getTitle()); } + public void execute(SendMessageToAllUserRequest request) { + List phoneNumberList = userRepository.findAll() + .stream() + .filter(user -> user.getAuthority() == Authority.USER) + .map(User::getPhoneNumber) + .toList(); + sendMessageService.execute(phoneNumberList, request.getText(), request.getTitle()); + } + private List formListFilter(FormType formType, Boolean isChangedToRegular) { List formList; if (formType.isMeister()) { formList = formRepository.findMeisterTalentFirstRoundForm(); } else { - if(isChangedToRegular) - formList = formRepository.findChangedToRegularFirstRoundForm(); - else - formList = formRepository.findNotExistsMeisterTalentAndChangedToRegularFirstRoundForm(); + if (isChangedToRegular) formList = formRepository.findChangedToRegularFirstRoundForm(); + else formList = formRepository.findNotExistsMeisterTalentAndChangedToRegularFirstRoundForm(); } return formList; } private List phoneNumberListConvert(List formList) { - return formList.stream() + return formList + .stream() .map(form -> form.getUser().getPhoneNumber()) .toList(); } diff --git a/src/main/java/com/bamdoliro/maru/presentation/message/MessageController.java b/src/main/java/com/bamdoliro/maru/presentation/message/MessageController.java index 362569de..2b2902e2 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/message/MessageController.java +++ b/src/main/java/com/bamdoliro/maru/presentation/message/MessageController.java @@ -4,6 +4,7 @@ import com.bamdoliro.maru.domain.user.domain.User; import com.bamdoliro.maru.presentation.message.dto.request.SendMessageByStatusRequest; import com.bamdoliro.maru.presentation.message.dto.request.SendMessageByTypeRequest; +import com.bamdoliro.maru.presentation.message.dto.request.SendMessageToAllUserRequest; import com.bamdoliro.maru.shared.auth.AuthenticationPrincipal; import com.bamdoliro.maru.shared.auth.Authority; import jakarta.validation.Valid; @@ -35,4 +36,13 @@ public void sendMessageByType( ) { sendMessageUseCase.execute(request); } + + @ResponseStatus(HttpStatus.NO_CONTENT) + @PostMapping("/all") + public void sendMessageToAllUser( + @AuthenticationPrincipal(authority = Authority.ADMIN) User user, + @RequestBody @Valid SendMessageToAllUserRequest request + ) { + sendMessageUseCase.execute(request); + } } diff --git a/src/main/java/com/bamdoliro/maru/presentation/message/dto/request/SendMessageToAllUserRequest.java b/src/main/java/com/bamdoliro/maru/presentation/message/dto/request/SendMessageToAllUserRequest.java new file mode 100644 index 00000000..28e5fbb4 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/message/dto/request/SendMessageToAllUserRequest.java @@ -0,0 +1,18 @@ +package com.bamdoliro.maru.presentation.message.dto.request; + +import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class SendMessageToAllUserRequest { + + @NotBlank(message = "필수값입니다.") + private String title; + + @NotBlank(message = "필수값입니다.") + private String text; +} diff --git a/src/test/java/com/bamdoliro/maru/application/message/SendMessageUseCaseTest.java b/src/test/java/com/bamdoliro/maru/application/message/SendMessageUseCaseTest.java index 86fb1dff..fc912263 100644 --- a/src/test/java/com/bamdoliro/maru/application/message/SendMessageUseCaseTest.java +++ b/src/test/java/com/bamdoliro/maru/application/message/SendMessageUseCaseTest.java @@ -4,12 +4,17 @@ import com.bamdoliro.maru.domain.form.domain.type.FormStatus; import com.bamdoliro.maru.domain.form.domain.type.FormType; import com.bamdoliro.maru.domain.form.service.CalculateFormScoreService; +import com.bamdoliro.maru.domain.user.domain.User; +import com.bamdoliro.maru.domain.user.domain.type.Authority; import com.bamdoliro.maru.infrastructure.message.SendMessageService; import com.bamdoliro.maru.infrastructure.message.exception.FailedToSendException; import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.infrastructure.persistence.user.UserRepository; import com.bamdoliro.maru.presentation.message.dto.request.SendMessageByStatusRequest; import com.bamdoliro.maru.presentation.message.dto.request.SendMessageByTypeRequest; +import com.bamdoliro.maru.presentation.message.dto.request.SendMessageToAllUserRequest; import com.bamdoliro.maru.shared.fixture.FormFixture; +import com.bamdoliro.maru.shared.fixture.UserFixture; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -17,6 +22,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import java.util.ArrayList; import java.util.List; import static org.mockito.BDDMockito.given; @@ -38,6 +44,9 @@ public class SendMessageUseCaseTest { @Mock private CalculateFormScoreService calculateFormScoreService; + @Mock + private UserRepository userRepository; + @Test void 원서를_최종제출한_학생들에게_메시지를_보낸다() { @@ -274,4 +283,46 @@ public class SendMessageUseCaseTest { verify(formRepository, times(1)).findMeisterTalentFirstRoundForm(); verify(sendMessageService, never()).execute(anyList(), anyString(), anyString()); } + + @Test + void 어드민을_제외한_전체_유저에게_메시지를_보낸다() { + + //given + List userList = new ArrayList<>(); + userList.add(UserFixture.createUser()); + userList.add(UserFixture.createUser()); + userList.add(UserFixture.createAdminUser()); + List phoneNumberList = userList.stream() + .filter(user -> user.getAuthority() == Authority.USER) + .map(User::getPhoneNumber) + .toList(); + + when(userRepository.findAll()).thenReturn(userList); + SendMessageToAllUserRequest request = new SendMessageToAllUserRequest("부산소마고 공지사항", "부산소마고 공지사항입니다."); + + //when + sendMessageUseCase.execute(request); + + //then + verify(userRepository, times(1)).findAll(); + verify(sendMessageService, times(1)).execute(phoneNumberList, request.getText(), request.getTitle()); + } + + @Test + void 어드민이_아닌_유저가_아무도_없다면_오류가_발생한다() { + + //given + List userList = new ArrayList<>(); + when(userRepository.findAll()).thenReturn(userList); + SendMessageToAllUserRequest request = new SendMessageToAllUserRequest("부산소마고 공지사항", "부산소마고 공지사항입니다."); + willThrow(new FailedToSendException()).given(sendMessageService).execute(anyList(), anyString(), anyString()); + + //when + Assertions.assertThrows(FailedToSendException.class, + () -> sendMessageUseCase.execute(request)); + + //then + verify(userRepository, times(1)).findAll(); // UserRepository의 findAll 메소드가 호출되었는지 검증 + verify(sendMessageService, times(1)).execute(anyList(), anyString(), anyString()); // sendMessageService의 execute 메소드가 호출되었는지 검증 + } } diff --git a/src/test/java/com/bamdoliro/maru/presentation/message/MessageControllerTest.java b/src/test/java/com/bamdoliro/maru/presentation/message/MessageControllerTest.java index f6d0fce7..2645e66d 100644 --- a/src/test/java/com/bamdoliro/maru/presentation/message/MessageControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/presentation/message/MessageControllerTest.java @@ -3,8 +3,10 @@ import com.bamdoliro.maru.domain.form.domain.type.FormStatus; import com.bamdoliro.maru.domain.form.domain.type.FormType; import com.bamdoliro.maru.domain.user.domain.User; +import com.bamdoliro.maru.infrastructure.message.exception.FailedToSendException; import com.bamdoliro.maru.presentation.message.dto.request.SendMessageByStatusRequest; import com.bamdoliro.maru.presentation.message.dto.request.SendMessageByTypeRequest; +import com.bamdoliro.maru.presentation.message.dto.request.SendMessageToAllUserRequest; import com.bamdoliro.maru.shared.fixture.AuthFixture; import com.bamdoliro.maru.shared.fixture.UserFixture; import com.bamdoliro.maru.shared.util.RestDocsTestSupport; @@ -168,4 +170,47 @@ public class MessageControllerTest extends RestDocsTestSupport { ) )); } + + @Test + void 어드민을_제외한_전체_유저에게_메시지를_발송한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + + SendMessageToAllUserRequest request = new SendMessageToAllUserRequest("부산소마고 공지사항", "테스트임니다.."); + willDoNothing().given(sendMessageUseCase).execute(request); + + mockMvc.perform(post("/message/all") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isNoContent()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("title").type(JsonFieldType.STRING).description("문자 메시지 제목"), + fieldWithPath("text").type(JsonFieldType.STRING).description("문자 메시지 내용") + ) + )); + } + + @Test + void 어드민을_제외한_유저가_아무도_없으면_오류가_발생한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + + SendMessageToAllUserRequest request = new SendMessageToAllUserRequest("부산소마고 공지사항", "테스트임니다.."); + + willThrow(new FailedToSendException()).given(sendMessageUseCase).execute(any(SendMessageToAllUserRequest.class)); + + mockMvc.perform(post("/message/all") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isInternalServerError()) + .andDo(restDocs.document()); + } }