diff --git a/src/main/java/in/koreatech/koin/domain/team/recruitment/model/TeamRecruitmentChatRoom.java b/src/main/java/in/koreatech/koin/domain/team/recruitment/model/TeamRecruitmentChatRoom.java index d4cb22717a..3139334077 100644 --- a/src/main/java/in/koreatech/koin/domain/team/recruitment/model/TeamRecruitmentChatRoom.java +++ b/src/main/java/in/koreatech/koin/domain/team/recruitment/model/TeamRecruitmentChatRoom.java @@ -125,10 +125,6 @@ public void removeMember(TeamRecruitmentChatMember member) { } } - public void markReadOnly() { - this.status = TeamRecruitmentChatRoomStatus.READ_ONLY; - } - @Transient public boolean isActive() { return status == TeamRecruitmentChatRoomStatus.ACTIVE; diff --git a/src/main/java/in/koreatech/koin/domain/team/recruitment/scheduler/TeamRecruitmentDeadlineCloseProcessor.java b/src/main/java/in/koreatech/koin/domain/team/recruitment/scheduler/TeamRecruitmentDeadlineCloseProcessor.java index eb0a9a6afa..68f7dd4b3b 100644 --- a/src/main/java/in/koreatech/koin/domain/team/recruitment/scheduler/TeamRecruitmentDeadlineCloseProcessor.java +++ b/src/main/java/in/koreatech/koin/domain/team/recruitment/scheduler/TeamRecruitmentDeadlineCloseProcessor.java @@ -2,7 +2,6 @@ import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentApplicationStatus.ACCEPTED; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentApplicationStatus.PENDING; -import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomStatus.ACTIVE; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomType.TEAM; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentNotificationTargetType.CHAT_ROOM; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentNotificationTargetType.MY_APPLICATIONS; @@ -69,7 +68,6 @@ public void closeIfExpired(Integer recruitmentId, LocalDate today) { recruitment.close(); recruitmentRepository.save(recruitment); rejectPendingApplications(recruitment, pendingApplications); - markRoomsReadOnly(recruitmentId); notifyRejectedApplications(recruitment, pendingApplications); notifyAcceptedMembers(recruitment, teamRoom, acceptedApplications); } @@ -105,19 +103,6 @@ private void rejectPendingApplications( } } - private void markRoomsReadOnly(Integer recruitmentId) { - List chatRooms = chatRoomRepository.findAllByRecruitment_Id(recruitmentId); - if (chatRooms == null) { - return; - } - for (TeamRecruitmentChatRoom chatRoom : chatRooms) { - if (chatRoom.getStatus() == ACTIVE) { - chatRoom.markReadOnly(); - chatRoomRepository.save(chatRoom); - } - } - } - private void notifyRejectedApplications( TeamRecruitment recruitment, List pendingApplications diff --git a/src/main/java/in/koreatech/koin/domain/team/recruitment/service/TeamRecruitmentClosureService.java b/src/main/java/in/koreatech/koin/domain/team/recruitment/service/TeamRecruitmentClosureService.java index 8ca9fec474..83d6d84a90 100644 --- a/src/main/java/in/koreatech/koin/domain/team/recruitment/service/TeamRecruitmentClosureService.java +++ b/src/main/java/in/koreatech/koin/domain/team/recruitment/service/TeamRecruitmentClosureService.java @@ -2,7 +2,6 @@ import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentApplicationStatus.ACCEPTED; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentApplicationStatus.PENDING; -import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomStatus.ACTIVE; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentNotificationTargetType.CHAT_ROOM; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentNotificationTargetType.MY_APPLICATIONS; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentNotificationType.APPLICATION_REJECTED; @@ -55,15 +54,13 @@ public class TeamRecruitmentClosureService { private final TeamRecruitmentOutboxEventRepository outboxEventRepository; /** - * 대기 중인 지원서를 거절하고, 모든 채팅방을 읽기 전용으로 바꾸고, - * 대기 중이던 지원자와 승인된 팀원에게 알림을 남긴다. + * 대기 중인 지원서를 거절하고, 대기 중이던 지원자와 승인된 팀원에게 알림을 남긴다. */ public void onClosed(TeamRecruitment recruitment) { List pending = findApplications(recruitment.getId(), PENDING); List accepted = findApplications(recruitment.getId(), ACCEPTED); rejectAll(pending, RECRUITMENT_CLOSED_REASON); - markRoomsReadOnly(recruitment.getId()); notifyRejected(recruitment, pending, closedRejectedMessage(recruitment)); notifyAccepted(recruitment, accepted, RECRUITMENT_CLOSED, closedMessage(recruitment)); } @@ -76,7 +73,6 @@ public void onDeleted(TeamRecruitment recruitment) { List accepted = findApplications(recruitment.getId(), ACCEPTED); rejectAll(pending, RECRUITMENT_DELETED_REASON); - markRoomsReadOnly(recruitment.getId()); notifyRejected(recruitment, pending, deletedRejectedMessage(recruitment)); notifyAccepted(recruitment, accepted, RECRUITMENT_DELETED, deletedMessage(recruitment)); } @@ -106,16 +102,6 @@ private void rejectAll(List applications, String rea applications.forEach(application -> application.reject(reason)); } - private void markRoomsReadOnly(Integer recruitmentId) { - List chatRooms = chatRoomRepository.findAllByRecruitment_Id(recruitmentId); - if (chatRooms == null) { - return; - } - chatRooms.stream() - .filter(chatRoom -> chatRoom.getStatus() == ACTIVE) - .forEach(TeamRecruitmentChatRoom::markReadOnly); - } - private void notifyRejected( TeamRecruitment recruitment, List pending, diff --git a/src/test/java/in/koreatech/koin/acceptance/domain/TeamRecruitmentApplicationFlowApiTest.java b/src/test/java/in/koreatech/koin/acceptance/domain/TeamRecruitmentApplicationFlowApiTest.java index e2d9cc6f1e..3450689a9e 100644 --- a/src/test/java/in/koreatech/koin/acceptance/domain/TeamRecruitmentApplicationFlowApiTest.java +++ b/src/test/java/in/koreatech/koin/acceptance/domain/TeamRecruitmentApplicationFlowApiTest.java @@ -5,7 +5,6 @@ import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentApplicationStatus.REJECTED; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentCategory.PROJECT; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomStatus.ACTIVE; -import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomStatus.READ_ONLY; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomType.DIRECT; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomType.TEAM; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentMeetingType.ONLINE; @@ -316,7 +315,7 @@ private void assertRole( } @Test - void 수동_마감된_ACCEPTED_지원서는_DIRECT_CTA와_생성_조건이_모두_닫힌다() throws Exception { + void 수동_마감된_ACCEPTED_지원서는_ACTIVE_TEAM_방이_있어_DIRECT를_생성할_수_있다() throws Exception { TeamRecruitment recruitment = recruitmentContext.recruitment(); TeamRecruitmentApplication application = savePendingApplication(recruitment); @@ -331,13 +330,15 @@ private void assertRole( .header("Authorization", "Bearer " + authorToken)) .andExpect(status().isOk()) .andExpect(jsonPath("$.applications[0].status").value("ACCEPTED")) - .andExpect(jsonPath("$.applications[0].can_open_direct_chat").value(false)); + .andExpect(jsonPath("$.applications[0].can_open_direct_chat").value(true)); mockMvc.perform(post("/chatroom/team-recruitment/{recruitmentId}/applications/{applicationId}/direct", recruitment.getId(), application.getId()) .header("Authorization", "Bearer " + authorToken)) - .andExpect(status().isConflict()) - .andExpect(jsonPath("$.code").value("TEAM_RECRUITMENT_CLOSED")); + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.chat_room_id").isNumber()) + .andExpect(jsonPath("$.room_type").value("DIRECT")) + .andExpect(jsonPath("$.status").value("ACTIVE")); } @Test @@ -445,20 +446,20 @@ private void assertRole( .andExpect(status().isNoContent()); assertThat(chatRoomRepository.findById(directRoom.getId()).orElseThrow().getStatus()) - .isEqualTo(READ_ONLY); + .isEqualTo(ACTIVE); mockMvc.perform(post("/chatroom/team-recruitment/{recruitmentId}/applications/{applicationId}/direct", recruitment.getId(), application.getId()) .header("Authorization", "Bearer " + authorToken)) .andExpect(status().isOk()) .andExpect(jsonPath("$.chat_room_id").value(directRoom.getId())) - .andExpect(jsonPath("$.status").value("READ_ONLY")); + .andExpect(jsonPath("$.status").value("ACTIVE")); mockMvc.perform(get("/chatroom/team-recruitment/{recruitmentId}/{chatRoomId}", recruitment.getId(), directRoom.getId()) .header("Authorization", "Bearer " + authorToken)) .andExpect(status().isOk()) - .andExpect(jsonPath("$.status").value("READ_ONLY")); + .andExpect(jsonPath("$.status").value("ACTIVE")); } @Test diff --git a/src/test/java/in/koreatech/koin/acceptance/domain/TeamRecruitmentArticleFlowApiTest.java b/src/test/java/in/koreatech/koin/acceptance/domain/TeamRecruitmentArticleFlowApiTest.java index 8a10705eb8..e9d7cf5658 100644 --- a/src/test/java/in/koreatech/koin/acceptance/domain/TeamRecruitmentArticleFlowApiTest.java +++ b/src/test/java/in/koreatech/koin/acceptance/domain/TeamRecruitmentArticleFlowApiTest.java @@ -5,7 +5,6 @@ import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentApplicationStatus.REJECTED; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentCategory.PROJECT; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomStatus.ACTIVE; -import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomStatus.READ_ONLY; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomType.TEAM; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentMeetingType.ONLINE; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentNotificationTargetType.MY_APPLICATIONS; @@ -124,7 +123,7 @@ void setUp() { } @Test - @DisplayName("수동 마감하면 대기 지원서가 거절되고 채팅방이 READ_ONLY 로 바뀌며 알림이 남는다") + @DisplayName("수동 마감하면 대기 지원서가 거절되고 채팅방은 ACTIVE 유지되며 알림이 남는다") void 수동_마감_후속_처리() throws Exception { TeamRecruitment recruitment = saveGeneralRecruitment("수동 마감", 3, 0); TeamRecruitmentChatRoom teamRoom = saveTeamRoom(recruitment); @@ -139,7 +138,7 @@ void setUp() { assertThat(applicationRepository.findById(application.getId()).orElseThrow().getStatus()) .isEqualTo(REJECTED); assertThat(chatRoomRepository.findById(teamRoom.getId()).orElseThrow().getStatus()) - .isEqualTo(READ_ONLY); + .isEqualTo(ACTIVE); assertThat(notificationRepository.findAllByRecipient_IdAndIsDeletedFalse(applicant.getUser().getId())) .extracting(TeamRecruitmentNotification::getType) .contains(APPLICATION_REJECTED); @@ -161,7 +160,7 @@ void setUp() { assertThat(applicationRepository.findById(application.getId()).orElseThrow().getDecisionReason()) .isEqualTo("RECRUITMENT_DELETED"); assertThat(chatRoomRepository.findById(teamRoom.getId()).orElseThrow().getStatus()) - .isEqualTo(READ_ONLY); + .isEqualTo(ACTIVE); assertThat(notificationRepository.findAllByRecipient_IdAndIsDeletedFalse(applicant.getUser().getId())) .extracting(TeamRecruitmentNotification::getMessagePreview) .anyMatch(message -> message.contains("삭제되어")); diff --git a/src/test/java/in/koreatech/koin/acceptance/domain/TeamRecruitmentDeadlineCloseIntegrationTest.java b/src/test/java/in/koreatech/koin/acceptance/domain/TeamRecruitmentDeadlineCloseIntegrationTest.java index 93f52a1faf..13bdecc3a9 100644 --- a/src/test/java/in/koreatech/koin/acceptance/domain/TeamRecruitmentDeadlineCloseIntegrationTest.java +++ b/src/test/java/in/koreatech/koin/acceptance/domain/TeamRecruitmentDeadlineCloseIntegrationTest.java @@ -5,7 +5,6 @@ import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentApplicationStatus.REJECTED; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentCategory.PROJECT; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomStatus.ACTIVE; -import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomStatus.READ_ONLY; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomType.DIRECT; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomType.TEAM; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentMeetingType.ONLINE; @@ -188,7 +187,7 @@ private void assertResults(Scenario scenario) { assertThat(successfulRecruitment.getStatus()).isEqualTo(CLOSED); assertThat(successfulPending.getStatus()).isEqualTo(REJECTED); assertThat(successfulPending.getDecisionReason()).isEqualTo("RECRUITMENT_CLOSED"); - assertThat(successfulTeamRoom.getStatus()).isEqualTo(READ_ONLY); + assertThat(successfulTeamRoom.getStatus()).isEqualTo(ACTIVE); assertThat(notificationRepository.findForOutbox( scenario.successfulApplicantId(), APPLICATION_REJECTED, diff --git a/src/test/java/in/koreatech/koin/unit/domain/team/recruitment/model/TeamRecruitmentDirectChatPolicyTest.java b/src/test/java/in/koreatech/koin/unit/domain/team/recruitment/model/TeamRecruitmentDirectChatPolicyTest.java index d472623aff..73d7b8be4e 100644 --- a/src/test/java/in/koreatech/koin/unit/domain/team/recruitment/model/TeamRecruitmentDirectChatPolicyTest.java +++ b/src/test/java/in/koreatech/koin/unit/domain/team/recruitment/model/TeamRecruitmentDirectChatPolicyTest.java @@ -44,7 +44,7 @@ class TeamRecruitmentDirectChatPolicyTest { } @Test - void 수동_기한_마감된_ACCEPTED_지원서는_READ_ONLY_TEAM_방이면_DIRECT를_열수없다() { + void READ_ONLY_TEAM_방이면_신규_DIRECT를_열수없다() { TeamRecruitment recruitment = recruitment(CLOSED); assertThat(canOpen(ACCEPTED, false, recruitment, teamRoom(recruitment, READ_ONLY))).isFalse(); diff --git a/src/test/java/in/koreatech/koin/unit/domain/team/recruitment/scheduler/TeamRecruitmentDeadlineCloseProcessorTest.java b/src/test/java/in/koreatech/koin/unit/domain/team/recruitment/scheduler/TeamRecruitmentDeadlineCloseProcessorTest.java index 1459a176ec..b273cae2a3 100644 --- a/src/test/java/in/koreatech/koin/unit/domain/team/recruitment/scheduler/TeamRecruitmentDeadlineCloseProcessorTest.java +++ b/src/test/java/in/koreatech/koin/unit/domain/team/recruitment/scheduler/TeamRecruitmentDeadlineCloseProcessorTest.java @@ -4,7 +4,6 @@ import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentApplicationStatus.PENDING; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentApplicationStatus.REJECTED; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomStatus.ACTIVE; -import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomStatus.READ_ONLY; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomType.DIRECT; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentChatRoomType.TEAM; import static in.koreatech.koin.domain.team.recruitment.enums.TeamRecruitmentStatus.CLOSED; @@ -82,7 +81,6 @@ class CloseExpiredRecruitments { stubApplications(pending, accepted); when(chatRoomRepository.findByRecruitment_IdAndRoomScopeKey(1, "TEAM")) .thenReturn(Optional.of(teamRoom)); - when(chatRoomRepository.findAllByRecruitment_Id(1)).thenReturn(List.of(teamRoom, directRoom)); when(outboxEventRepository.findByEventKey(any())).thenReturn(Optional.empty()); when(notificationRepository.save(any())).thenAnswer(invocation -> { TeamRecruitmentNotification notification = invocation.getArgument(0); @@ -100,11 +98,10 @@ class CloseExpiredRecruitments { assertThat(pending.getStatus()).isEqualTo(REJECTED); assertThat(pending.getDecisionReason()).isEqualTo("RECRUITMENT_CLOSED"); assertThat(accepted.getStatus()).isEqualTo(ACCEPTED); - assertThat(teamRoom.getStatus()).isEqualTo(READ_ONLY); - assertThat(directRoom.getStatus()).isEqualTo(READ_ONLY); + assertThat(teamRoom.getStatus()).isEqualTo(ACTIVE); + assertThat(directRoom.getStatus()).isEqualTo(ACTIVE); verify(applicationRepository).save(pending); - verify(chatRoomRepository).save(teamRoom); - verify(chatRoomRepository).save(directRoom); + verify(chatRoomRepository, never()).save(any()); verify(notificationRepository, org.mockito.Mockito.times(2)).save(any()); verify(outboxEventRepository, org.mockito.Mockito.times(2)).save(any()); ArgumentCaptor outboxCaptor = @@ -152,7 +149,6 @@ class CloseExpiredRecruitments { )).thenReturn(new PageImpl<>(List.of(accepted))); when(chatRoomRepository.findByRecruitment_IdAndRoomScopeKey(1, "TEAM")) .thenReturn(Optional.empty()); - when(chatRoomRepository.findAllByRecruitment_Id(1)).thenReturn(List.of()); IllegalStateException exception = assertThrows( IllegalStateException.class, @@ -180,7 +176,6 @@ class CloseExpiredRecruitments { )).thenReturn(new PageImpl<>(List.of())); when(chatRoomRepository.findByRecruitment_IdAndRoomScopeKey(1, "TEAM")) .thenReturn(Optional.empty()); - when(chatRoomRepository.findAllByRecruitment_Id(1)).thenReturn(List.of()); processor.closeIfExpired(1, TODAY);