diff --git a/src/main/java/space/space_spring/controller/ChattingController.java b/src/main/java/space/space_spring/controller/ChattingController.java deleted file mode 100644 index 2b0d7963..00000000 --- a/src/main/java/space/space_spring/controller/ChattingController.java +++ /dev/null @@ -1,56 +0,0 @@ -package space.space_spring.controller; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.messaging.handler.annotation.*; -import org.springframework.messaging.simp.annotation.SubscribeMapping; -import org.springframework.web.bind.annotation.RestController; -import space.space_spring.argumentResolver.userSpace.CheckUserSpace; -import space.space_spring.dto.chat.request.ChatMessageRequest; -import space.space_spring.dto.chat.response.ChatMessageLogResponse; -import space.space_spring.dto.chat.response.ChatMessageResponse; -import space.space_spring.service.ChattingService; - -import java.io.IOException; -import java.util.Map; - -@Slf4j -@RestController -@RequiredArgsConstructor -public class ChattingController { - - private final ChattingService chattingService; - - - @MessageMapping("/chat/{chatRoomId}") // {chatRoomId} 채팅방으로 보낸 메세지 매핑 - @SendTo("/topic/chat/{chatRoomId}") // {chatRoomId} 채팅방을 구독한 곳들로 메세지 전송 - @CheckUserSpace(required = false) - public ChatMessageResponse sendChatMessage (@Payload ChatMessageRequest chatMessageRequest, @DestinationVariable Long chatRoomId, - @Header("simpSessionAttributes") Map sessionAttributes) throws IOException { - Long senderId = (Long) sessionAttributes.get("userId"); -// log.info(senderId + " 님이 " + chatRoomId + " 채팅방으로 " + chatMessageRequest.getContent() + " 전송"); - - return chattingService.sendChatMessage(senderId, chatMessageRequest, chatRoomId); - } - - @SubscribeMapping("/chat/{chatRoomId}") // {chatRoomId} 채팅방을 구독 - @CheckUserSpace(required = false) - public ChatMessageLogResponse subscribeChatRoom (@DestinationVariable Long chatRoomId, @Header("simpSessionAttributes") Map sessionAttributes) { -// log.info(chatRoomId + " 채팅방 구독"); - sessionAttributes.put("chatRoomId", chatRoomId); - return chattingService.readChatMessageLog(chatRoomId); - } - - // socket disconnect 시 호출 -// @EventListener -// @CheckUserSpace(required = false) -// public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) { -// StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage()); -// Map sessionAttributes = headerAccessor.getSessionAttributes(); -// -// Long userId = (Long) sessionAttributes.get("userId"); -// Long chatRoomId = (Long) sessionAttributes.get("chatRoomId"); -// log.info("userId: " + userId + " chatRoomid: " + chatRoomId); -// userChatRoomService.saveLastReadTime(userId, chatRoomId); -// } -} diff --git a/src/main/java/space/space_spring/dao/chat/ChattingRepository.java b/src/main/java/space/space_spring/dao/chat/ChattingRepository.java deleted file mode 100644 index 975186d9..00000000 --- a/src/main/java/space/space_spring/dao/chat/ChattingRepository.java +++ /dev/null @@ -1,17 +0,0 @@ -package space.space_spring.dao.chat; - -import org.springframework.data.mongodb.repository.MongoRepository; -import org.springframework.stereotype.Repository; -import space.space_spring.entity.document.ChatMessage; - -import java.time.LocalDateTime; -import java.util.List; - -@Repository -public interface ChattingRepository extends MongoRepository { - List findByChatRoomId(Long chatRoomId); - - ChatMessage findTopByChatRoomIdOrderByCreatedAtDesc(Long chatRoomId); - - int countByChatRoomIdAndCreatedAtBetween(Long chatRoomId, LocalDateTime lastReadTime, LocalDateTime lastUpdateTime); -} diff --git a/src/main/java/space/space_spring/dao/chat/custom/ChatRoomRepositoryCustom.java b/src/main/java/space/space_spring/dao/chat/custom/ChatRoomRepositoryCustom.java deleted file mode 100644 index 00ab57cc..00000000 --- a/src/main/java/space/space_spring/dao/chat/custom/ChatRoomRepositoryCustom.java +++ /dev/null @@ -1,11 +0,0 @@ -package space.space_spring.dao.chat.custom; - -import space.space_spring.entity.ChatRoom; -import space.space_spring.domain.space.model.entity.Space; -import space.space_spring.domain.user.model.entity.User; - -import java.util.List; - -public interface ChatRoomRepositoryCustom { - List findByUserAndSpace(User user, Space space); -} diff --git a/src/main/java/space/space_spring/controller/ChatRoomController.java b/src/main/java/space/space_spring/domain/chat/chatroom/controller/ChatRoomController.java similarity index 88% rename from src/main/java/space/space_spring/controller/ChatRoomController.java rename to src/main/java/space/space_spring/domain/chat/chatroom/controller/ChatRoomController.java index 50392f3d..546da4e3 100644 --- a/src/main/java/space/space_spring/controller/ChatRoomController.java +++ b/src/main/java/space/space_spring/domain/chat/chatroom/controller/ChatRoomController.java @@ -1,4 +1,4 @@ -package space.space_spring.controller; +package space.space_spring.domain.chat.chatroom.controller; import lombok.RequiredArgsConstructor; import org.springframework.validation.BindingResult; @@ -6,15 +6,15 @@ import org.springframework.web.bind.annotation.*; import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuth; import space.space_spring.argumentResolver.userSpace.UserSpaceAuth; -import space.space_spring.dto.chat.request.CreateChatRoomRequest; -import space.space_spring.dto.chat.request.JoinChatRoomRequest; -import space.space_spring.dto.chat.response.ChatSuccessResponse; -import space.space_spring.dto.chat.response.CreateChatRoomResponse; -import space.space_spring.dto.chat.response.ReadChatRoomMemberResponse; -import space.space_spring.dto.chat.response.ReadChatRoomResponse; +import space.space_spring.domain.chat.chatroom.model.request.CreateChatRoomRequest; +import space.space_spring.domain.chat.chatroom.model.request.JoinChatRoomRequest; +import space.space_spring.domain.chat.chatroom.model.response.ChatSuccessResponse; +import space.space_spring.domain.chat.chatroom.model.response.CreateChatRoomResponse; +import space.space_spring.domain.chat.chatroom.model.response.ReadChatRoomMemberResponse; +import space.space_spring.domain.chat.chatroom.model.response.ReadChatRoomResponse; import space.space_spring.exception.CustomException; import space.space_spring.response.BaseResponse; -import space.space_spring.service.ChatRoomService; +import space.space_spring.domain.chat.chatroom.service.component.ChatRoomService; import space.space_spring.service.S3Uploader; import java.io.IOException; diff --git a/src/main/java/space/space_spring/entity/ChatRoom.java b/src/main/java/space/space_spring/domain/chat/chatroom/model/ChatRoom.java similarity index 68% rename from src/main/java/space/space_spring/entity/ChatRoom.java rename to src/main/java/space/space_spring/domain/chat/chatroom/model/ChatRoom.java index aca0fa99..5c3afabd 100644 --- a/src/main/java/space/space_spring/entity/ChatRoom.java +++ b/src/main/java/space/space_spring/domain/chat/chatroom/model/ChatRoom.java @@ -1,22 +1,23 @@ -package space.space_spring.entity; +package space.space_spring.domain.chat.chatroom.model; import jakarta.annotation.Nullable; import jakarta.persistence.*; -import lombok.AllArgsConstructor; +import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import org.hibernate.annotations.Comment; + +import space.space_spring.entity.BaseEntity; import space.space_spring.domain.space.model.entity.Space; @Entity @Getter -@Builder -@NoArgsConstructor -@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) @Comment("채팅방") @Table(name = "Chat_Room") -public class ChatRoom extends BaseEntity{ +public class ChatRoom extends BaseEntity { @Id @GeneratedValue @@ -33,10 +34,18 @@ public class ChatRoom extends BaseEntity{ private String name; @Comment("채팅방 이미지") - @Nullable + @NotNull @Column(name = "chat_room_img") private String img; + @Builder(access = AccessLevel.PRIVATE) + private ChatRoom(Long id, Space space, String name, String img) { + this.id = id; + this.space = space; + this.name = name; + this.img = img; + } + public static ChatRoom of(Space space, String chatRoomName, String chatRoomImgUrl) { return ChatRoom.builder() .space(space) @@ -49,7 +58,4 @@ public void updateName(String name) { this.name = name; } - // // 양방향 매핑 -// @OneToMany(mappedBy = "chatRoom", cascade = CascadeType.ALL) -// private List userChatRooms; } diff --git a/src/main/java/space/space_spring/domain/chat/chatroom/model/ChatRooms.java b/src/main/java/space/space_spring/domain/chat/chatroom/model/ChatRooms.java new file mode 100644 index 00000000..d3e22c68 --- /dev/null +++ b/src/main/java/space/space_spring/domain/chat/chatroom/model/ChatRooms.java @@ -0,0 +1,42 @@ +package space.space_spring.domain.chat.chatroom.model; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; +import java.util.function.BiFunction; +import java.util.function.Function; +import space.space_spring.domain.chat.chatroom.model.dto.LastMessageInfoDto; +import space.space_spring.domain.chat.chatroom.model.response.ChatRoomResponse; + +public class ChatRooms { + + private List chatRooms; + + private ChatRooms(List chatRooms) { + this.chatRooms = chatRooms; + } + + public static ChatRooms of(List chatRooms) { + return new ChatRooms(chatRooms); + } + + public List toChatRoomResponses( + Long userId, + Function lastMessageFinder, + BiFunction unreadMessageCounter) { + return chatRooms.stream() + .map(chatRoom -> { + LastMessageInfoDto lastMessageInfo = lastMessageFinder.apply(chatRoom); + LocalDateTime lastUpdateTime = lastMessageInfo.getLastUpdateTime(); + HashMap lastContent = lastMessageInfo.getLastContent(); + + int unreadMsgCount = unreadMessageCounter.apply(userId, chatRoom); + + return ChatRoomResponse.create(chatRoom, lastContent, String.valueOf(lastUpdateTime), + unreadMsgCount); + }) + .filter(Objects::nonNull) + .toList(); + } +} diff --git a/src/main/java/space/space_spring/entity/UserChatRoom.java b/src/main/java/space/space_spring/domain/chat/chatroom/model/UserChatRoom.java similarity index 71% rename from src/main/java/space/space_spring/entity/UserChatRoom.java rename to src/main/java/space/space_spring/domain/chat/chatroom/model/UserChatRoom.java index 14bf2575..113c04c1 100644 --- a/src/main/java/space/space_spring/entity/UserChatRoom.java +++ b/src/main/java/space/space_spring/domain/chat/chatroom/model/UserChatRoom.java @@ -1,8 +1,9 @@ -package space.space_spring.entity; +package space.space_spring.domain.chat.chatroom.model; import jakarta.annotation.Nullable; import jakarta.persistence.*; -import lombok.AllArgsConstructor; +import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -10,15 +11,14 @@ import space.space_spring.domain.user.model.entity.User; import java.time.LocalDateTime; +import space.space_spring.entity.BaseEntity; @Entity @Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) @Comment("유저별 채팅방") @Table(name = "User_Chat_Room") -public class UserChatRoom extends BaseEntity{ +public class UserChatRoom extends BaseEntity { @Id @GeneratedValue @@ -36,10 +36,18 @@ public class UserChatRoom extends BaseEntity{ private User user; @Comment("마지막으로 읽은 시간") - @Nullable + @NotNull @Column(name = "last_read_time") private LocalDateTime lastReadTime; + @Builder(access = AccessLevel.PRIVATE) + private UserChatRoom(Long id, ChatRoom chatRoom, User user, LocalDateTime lastReadTime) { + this.id = id; + this.chatRoom = chatRoom; + this.user = user; + this.lastReadTime = lastReadTime; + } + public static UserChatRoom of(ChatRoom chatRoom, User user, LocalDateTime lastReadTime) { return UserChatRoom.builder() .chatRoom(chatRoom) diff --git a/src/main/java/space/space_spring/domain/chat/chatroom/model/UserChatRooms.java b/src/main/java/space/space_spring/domain/chat/chatroom/model/UserChatRooms.java new file mode 100644 index 00000000..6527dd1e --- /dev/null +++ b/src/main/java/space/space_spring/domain/chat/chatroom/model/UserChatRooms.java @@ -0,0 +1,30 @@ +package space.space_spring.domain.chat.chatroom.model; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import space.space_spring.domain.user.model.entity.User; + +public class UserChatRooms { + + private final List userChatRooms; + + private UserChatRooms(List userChatRooms) { + this.userChatRooms = Collections.unmodifiableList(userChatRooms); + } + + public static UserChatRooms of(List userChatRooms) { + return new UserChatRooms(userChatRooms); + } + + public boolean isUserJoined(Long userId) { + return userChatRooms.stream().anyMatch(userChatRoom -> userChatRoom.getUser().getUserId().equals(userId)); + } + + public List getUsers() { + return userChatRooms.stream() + .map(UserChatRoom::getUser) + .collect(Collectors.toUnmodifiableList()); + } + +} diff --git a/src/main/java/space/space_spring/domain/chat/chatroom/model/dto/LastMessageInfoDto.java b/src/main/java/space/space_spring/domain/chat/chatroom/model/dto/LastMessageInfoDto.java new file mode 100644 index 00000000..eda9dbb4 --- /dev/null +++ b/src/main/java/space/space_spring/domain/chat/chatroom/model/dto/LastMessageInfoDto.java @@ -0,0 +1,30 @@ +package space.space_spring.domain.chat.chatroom.model.dto; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; + +import java.time.LocalDateTime; +import java.util.HashMap; + +@Getter +public class LastMessageInfoDto { + + private LocalDateTime lastUpdateTime; + + private HashMap lastContent; + + @Builder(access = AccessLevel.PRIVATE) + private LastMessageInfoDto(LocalDateTime lastUpdateTime, HashMap lastContent) { + this.lastUpdateTime = lastUpdateTime; + this.lastContent = lastContent; + } + + public static LastMessageInfoDto of(LocalDateTime lastUpdateTime, HashMap lastContent) { + return LastMessageInfoDto.builder() + .lastUpdateTime(lastUpdateTime) + .lastContent(lastContent) + .build(); + } +} + diff --git a/src/main/java/space/space_spring/dto/chat/request/CreateChatRoomRequest.java b/src/main/java/space/space_spring/domain/chat/chatroom/model/request/CreateChatRoomRequest.java similarity index 87% rename from src/main/java/space/space_spring/dto/chat/request/CreateChatRoomRequest.java rename to src/main/java/space/space_spring/domain/chat/chatroom/model/request/CreateChatRoomRequest.java index e8143551..e502a392 100644 --- a/src/main/java/space/space_spring/dto/chat/request/CreateChatRoomRequest.java +++ b/src/main/java/space/space_spring/domain/chat/chatroom/model/request/CreateChatRoomRequest.java @@ -1,19 +1,15 @@ -package space.space_spring.dto.chat.request; +package space.space_spring.domain.chat.chatroom.model.request; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; -import lombok.Builder; import lombok.Getter; -import lombok.Setter; import org.springframework.web.multipart.MultipartFile; import java.util.List; @Getter -@Setter -@Builder public class CreateChatRoomRequest { @Size(min = 2, max = 15, message = "채팅방 이름은 2자 이상, 15자 이내의 문자열이어야 합니다.") diff --git a/src/main/java/space/space_spring/dto/chat/request/JoinChatRoomRequest.java b/src/main/java/space/space_spring/domain/chat/chatroom/model/request/JoinChatRoomRequest.java similarity index 52% rename from src/main/java/space/space_spring/dto/chat/request/JoinChatRoomRequest.java rename to src/main/java/space/space_spring/domain/chat/chatroom/model/request/JoinChatRoomRequest.java index 5b6e3d53..0be390dc 100644 --- a/src/main/java/space/space_spring/dto/chat/request/JoinChatRoomRequest.java +++ b/src/main/java/space/space_spring/domain/chat/chatroom/model/request/JoinChatRoomRequest.java @@ -1,17 +1,11 @@ -package space.space_spring.dto.chat.request; +package space.space_spring.domain.chat.chatroom.model.request; import jakarta.validation.constraints.NotEmpty; -import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Getter; -import lombok.NoArgsConstructor; import java.util.List; @Getter -@Builder -@NoArgsConstructor /* controller단 테스트 위해 적용*/ -@AllArgsConstructor public class JoinChatRoomRequest { @NotEmpty(message = "1명 이상의 멤버를 초대해야 합니다.") diff --git a/src/main/java/space/space_spring/domain/chat/chatroom/model/response/ChatRoomResponse.java b/src/main/java/space/space_spring/domain/chat/chatroom/model/response/ChatRoomResponse.java new file mode 100644 index 00000000..0009e9a8 --- /dev/null +++ b/src/main/java/space/space_spring/domain/chat/chatroom/model/response/ChatRoomResponse.java @@ -0,0 +1,45 @@ +package space.space_spring.domain.chat.chatroom.model.response; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import space.space_spring.domain.chat.chatroom.model.ChatRoom; + +import java.util.HashMap; + +@Getter +public class ChatRoomResponse { + private Long id; + + private String name; + + private String imgUrl; + + private HashMap lastMsg; + + private String lastTime; + + private int unreadMsgCount; + + @Builder(access = AccessLevel.PRIVATE) + private ChatRoomResponse(Long id, String name, String imgUrl, HashMap lastMsg, String lastTime, + int unreadMsgCount) { + this.id = id; + this.name = name; + this.imgUrl = imgUrl; + this.lastMsg = lastMsg; + this.lastTime = lastTime; + this.unreadMsgCount = unreadMsgCount; + } + + public static ChatRoomResponse create(ChatRoom chatRoom, HashMap lastMsg, String lastTime, int unreadMsgCount) { + return ChatRoomResponse.builder() + .id(chatRoom.getId()) + .name(chatRoom.getName()) + .imgUrl(chatRoom.getImg()) + .lastMsg(lastMsg) + .lastTime(lastTime) + .unreadMsgCount(unreadMsgCount) + .build(); + } +} diff --git a/src/main/java/space/space_spring/dto/chat/response/ChatSuccessResponse.java b/src/main/java/space/space_spring/domain/chat/chatroom/model/response/ChatSuccessResponse.java similarity index 56% rename from src/main/java/space/space_spring/dto/chat/response/ChatSuccessResponse.java rename to src/main/java/space/space_spring/domain/chat/chatroom/model/response/ChatSuccessResponse.java index abe6e481..c5ebf44d 100644 --- a/src/main/java/space/space_spring/dto/chat/response/ChatSuccessResponse.java +++ b/src/main/java/space/space_spring/domain/chat/chatroom/model/response/ChatSuccessResponse.java @@ -1,13 +1,18 @@ -package space.space_spring.dto.chat.response; +package space.space_spring.domain.chat.chatroom.model.response; +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @Getter -@Builder public class ChatSuccessResponse { private boolean isSuccess; + @Builder(access = AccessLevel.PRIVATE) + private ChatSuccessResponse(boolean isSuccess) { + this.isSuccess = isSuccess; + } + public static ChatSuccessResponse of(boolean isSuccess) { return ChatSuccessResponse.builder() .isSuccess(isSuccess) diff --git a/src/main/java/space/space_spring/dto/chat/response/CreateChatRoomResponse.java b/src/main/java/space/space_spring/domain/chat/chatroom/model/response/CreateChatRoomResponse.java similarity index 55% rename from src/main/java/space/space_spring/dto/chat/response/CreateChatRoomResponse.java rename to src/main/java/space/space_spring/domain/chat/chatroom/model/response/CreateChatRoomResponse.java index 79c73d5b..73293797 100644 --- a/src/main/java/space/space_spring/dto/chat/response/CreateChatRoomResponse.java +++ b/src/main/java/space/space_spring/domain/chat/chatroom/model/response/CreateChatRoomResponse.java @@ -1,15 +1,18 @@ -package space.space_spring.dto.chat.response; +package space.space_spring.domain.chat.chatroom.model.response; -import lombok.AllArgsConstructor; +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @Getter -@AllArgsConstructor -@Builder public class CreateChatRoomResponse { private Long chatRoomId; + @Builder(access = AccessLevel.PRIVATE) + private CreateChatRoomResponse(Long chatRoomId) { + this.chatRoomId = chatRoomId; + } + public static CreateChatRoomResponse of(Long id) { return CreateChatRoomResponse.builder() .chatRoomId(id) diff --git a/src/main/java/space/space_spring/dto/chat/response/ReadChatRoomMemberResponse.java b/src/main/java/space/space_spring/domain/chat/chatroom/model/response/ReadChatRoomMemberResponse.java similarity index 57% rename from src/main/java/space/space_spring/dto/chat/response/ReadChatRoomMemberResponse.java rename to src/main/java/space/space_spring/domain/chat/chatroom/model/response/ReadChatRoomMemberResponse.java index 6f0f7c06..d551f95a 100644 --- a/src/main/java/space/space_spring/dto/chat/response/ReadChatRoomMemberResponse.java +++ b/src/main/java/space/space_spring/domain/chat/chatroom/model/response/ReadChatRoomMemberResponse.java @@ -1,17 +1,21 @@ -package space.space_spring.dto.chat.response; +package space.space_spring.domain.chat.chatroom.model.response; +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import space.space_spring.domain.userSpace.model.UserInfoInSpace; -import java.util.ArrayList; import java.util.List; @Getter -@Builder public class ReadChatRoomMemberResponse { - private List userList = new ArrayList<>(); + private List userList; + + @Builder(access = AccessLevel.PRIVATE) + private ReadChatRoomMemberResponse(List userList) { + this.userList = userList; + } public static ReadChatRoomMemberResponse of(List userList) { return ReadChatRoomMemberResponse.builder() diff --git a/src/main/java/space/space_spring/dto/chat/response/ReadChatRoomResponse.java b/src/main/java/space/space_spring/domain/chat/chatroom/model/response/ReadChatRoomResponse.java similarity index 58% rename from src/main/java/space/space_spring/dto/chat/response/ReadChatRoomResponse.java rename to src/main/java/space/space_spring/domain/chat/chatroom/model/response/ReadChatRoomResponse.java index 1a16a13e..176c3967 100644 --- a/src/main/java/space/space_spring/dto/chat/response/ReadChatRoomResponse.java +++ b/src/main/java/space/space_spring/domain/chat/chatroom/model/response/ReadChatRoomResponse.java @@ -1,17 +1,21 @@ -package space.space_spring.dto.chat.response; +package space.space_spring.domain.chat.chatroom.model.response; -import lombok.AllArgsConstructor; +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import java.util.List; @Getter -@AllArgsConstructor -@Builder public class ReadChatRoomResponse { + private List chatRoomList; + @Builder(access = AccessLevel.PRIVATE) + private ReadChatRoomResponse(List chatRoomList) { + this.chatRoomList = chatRoomList; + } + public static ReadChatRoomResponse of(List chatRooms) { return ReadChatRoomResponse.builder() .chatRoomList(chatRooms) diff --git a/src/main/java/space/space_spring/dao/chat/ChatRoomRepository.java b/src/main/java/space/space_spring/domain/chat/chatroom/repository/ChatRoomRepository.java similarity index 62% rename from src/main/java/space/space_spring/dao/chat/ChatRoomRepository.java rename to src/main/java/space/space_spring/domain/chat/chatroom/repository/ChatRoomRepository.java index 4ddf3158..7d273a0d 100644 --- a/src/main/java/space/space_spring/dao/chat/ChatRoomRepository.java +++ b/src/main/java/space/space_spring/domain/chat/chatroom/repository/ChatRoomRepository.java @@ -1,9 +1,9 @@ -package space.space_spring.dao.chat; +package space.space_spring.domain.chat.chatroom.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import space.space_spring.dao.chat.custom.ChatRoomRepositoryCustom; -import space.space_spring.entity.ChatRoom; +import space.space_spring.domain.chat.chatroom.repository.custom.ChatRoomRepositoryCustom; +import space.space_spring.domain.chat.chatroom.model.ChatRoom; import space.space_spring.entity.enumStatus.BaseStatusType; @Repository diff --git a/src/main/java/space/space_spring/dao/chat/UserChatRoomRepository.java b/src/main/java/space/space_spring/domain/chat/chatroom/repository/UserChatRoomRepository.java similarity index 56% rename from src/main/java/space/space_spring/dao/chat/UserChatRoomRepository.java rename to src/main/java/space/space_spring/domain/chat/chatroom/repository/UserChatRoomRepository.java index d87348a8..0380a007 100644 --- a/src/main/java/space/space_spring/dao/chat/UserChatRoomRepository.java +++ b/src/main/java/space/space_spring/domain/chat/chatroom/repository/UserChatRoomRepository.java @@ -1,16 +1,15 @@ -package space.space_spring.dao.chat; +package space.space_spring.domain.chat.chatroom.repository; import org.springframework.data.jpa.repository.JpaRepository; -import space.space_spring.entity.ChatRoom; +import space.space_spring.domain.chat.chatroom.model.ChatRoom; +import space.space_spring.domain.chat.chatroom.model.UserChatRoom; import space.space_spring.domain.user.model.entity.User; -import space.space_spring.entity.UserChatRoom; import space.space_spring.entity.enumStatus.BaseStatusType; import java.util.List; - public interface UserChatRoomRepository extends JpaRepository { - UserChatRoom findByUserAndChatRoomAndStatus(User userByUserId, ChatRoom chatRoomByChatRoomId, BaseStatusType status); + UserChatRoom findByUserAndChatRoomAndStatus(User user, ChatRoom chatRoom, BaseStatusType status); List findByChatRoomAndStatus(ChatRoom chatRoom, BaseStatusType status); } diff --git a/src/main/java/space/space_spring/domain/chat/chatroom/repository/custom/ChatRoomRepositoryCustom.java b/src/main/java/space/space_spring/domain/chat/chatroom/repository/custom/ChatRoomRepositoryCustom.java new file mode 100644 index 00000000..9e1055fe --- /dev/null +++ b/src/main/java/space/space_spring/domain/chat/chatroom/repository/custom/ChatRoomRepositoryCustom.java @@ -0,0 +1,9 @@ +package space.space_spring.domain.chat.chatroom.repository.custom; + +import space.space_spring.domain.chat.chatroom.model.ChatRoom; + +import java.util.List; + +public interface ChatRoomRepositoryCustom { + List findByUserIdAndSpaceId(Long userId, Long spaceId); +} diff --git a/src/main/java/space/space_spring/dao/chat/custom/ChatRoomRepositoryImpl.java b/src/main/java/space/space_spring/domain/chat/chatroom/repository/custom/ChatRoomRepositoryImpl.java similarity index 59% rename from src/main/java/space/space_spring/dao/chat/custom/ChatRoomRepositoryImpl.java rename to src/main/java/space/space_spring/domain/chat/chatroom/repository/custom/ChatRoomRepositoryImpl.java index 51e53bea..f5aba3df 100644 --- a/src/main/java/space/space_spring/dao/chat/custom/ChatRoomRepositoryImpl.java +++ b/src/main/java/space/space_spring/domain/chat/chatroom/repository/custom/ChatRoomRepositoryImpl.java @@ -1,16 +1,15 @@ -package space.space_spring.dao.chat.custom; +package space.space_spring.domain.chat.chatroom.repository.custom; + +import static space.space_spring.domain.chat.chatroom.model.QChatRoom.chatRoom; +import static space.space_spring.domain.chat.chatroom.model.QUserChatRoom.userChatRoom; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; -import space.space_spring.entity.ChatRoom; -import space.space_spring.domain.space.model.entity.Space; -import space.space_spring.domain.user.model.entity.User; +import space.space_spring.domain.chat.chatroom.model.ChatRoom; import java.util.List; import space.space_spring.entity.enumStatus.BaseStatusType; -import static space.space_spring.entity.QChatRoom.chatRoom; -import static space.space_spring.entity.QUserChatRoom.userChatRoom; @RequiredArgsConstructor public class ChatRoomRepositoryImpl implements ChatRoomRepositoryCustom { @@ -18,14 +17,14 @@ public class ChatRoomRepositoryImpl implements ChatRoomRepositoryCustom { private final JPAQueryFactory jpaQueryFactory; @Override - public List findByUserAndSpace(User who, Space where) { + public List findByUserIdAndSpaceId(Long userId, Long spaceId) { return jpaQueryFactory .selectFrom(chatRoom) .join(userChatRoom).on( userChatRoom.chatRoom.eq(chatRoom) - .and(userChatRoom.user.eq(who)) + .and(userChatRoom.user.userId.eq(userId)) .and(userChatRoom.status.eq(BaseStatusType.ACTIVE))) - .where(chatRoom.space.eq(where) + .where(chatRoom.space.spaceId.eq(spaceId) .and(chatRoom.status.eq(BaseStatusType.ACTIVE))) .orderBy(chatRoom.lastModifiedAt.desc()) .fetch(); diff --git a/src/main/java/space/space_spring/domain/chat/chatroom/service/component/ChatRoomService.java b/src/main/java/space/space_spring/domain/chat/chatroom/service/component/ChatRoomService.java new file mode 100644 index 00000000..84855e24 --- /dev/null +++ b/src/main/java/space/space_spring/domain/chat/chatroom/service/component/ChatRoomService.java @@ -0,0 +1,220 @@ +package space.space_spring.domain.chat.chatroom.service.component; + +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import space.space_spring.domain.chat.chatroom.model.ChatRoom; +import space.space_spring.domain.chat.chatroom.model.ChatRooms; +import space.space_spring.domain.chat.chatroom.model.UserChatRooms; +import space.space_spring.domain.chat.chatroom.model.response.ChatRoomResponse; +import space.space_spring.domain.chat.chatroom.model.response.ChatSuccessResponse; +import space.space_spring.domain.chat.chatroom.model.response.CreateChatRoomResponse; +import space.space_spring.domain.chat.chatroom.model.response.ReadChatRoomMemberResponse; +import space.space_spring.domain.chat.chatroom.model.response.ReadChatRoomResponse; +import space.space_spring.domain.chat.chatroom.model.UserChatRoom; +import space.space_spring.domain.chat.chatroom.model.dto.LastMessageInfoDto; +import space.space_spring.domain.chat.chatroom.model.request.JoinChatRoomRequest; +import space.space_spring.domain.chat.chatroom.model.request.CreateChatRoomRequest; +import space.space_spring.domain.chat.chatroom.service.module.ChatRoomModuleService; +import space.space_spring.domain.chat.chatroom.service.module.UserChatRoomModuleService; +import space.space_spring.domain.chat.chatting.service.module.ChattingModuleService; +import space.space_spring.domain.space.model.entity.Space; +import space.space_spring.domain.user.model.entity.User; +import space.space_spring.domain.userSpace.model.UserInfoInSpace; +import space.space_spring.domain.userSpace.model.entity.UserSpace; +import space.space_spring.domain.chat.chatting.model.document.ChatMessage; + +import space.space_spring.entity.enumStatus.BaseStatusType; +import space.space_spring.exception.CustomException; +import space.space_spring.global.util.TimeUtils; +import space.space_spring.util.space.SpaceUtils; +import space.space_spring.util.user.UserUtils; + +import java.time.LocalDateTime; +import java.util.*; +import space.space_spring.util.userSpace.UserSpaceUtils; + +import static space.space_spring.response.status.BaseExceptionResponseStatus.*; + +@Service +@Slf4j +@RequiredArgsConstructor +public class ChatRoomService { + + private final UserUtils userUtils; + // findUserByUserId -> common module service + private final SpaceUtils spaceUtils; + // findSpaceBySpaceId -> common module service + private final UserSpaceUtils userSpaceUtils; + // findUserSpaceByUserAndSpace -> common module service + + private final ChatRoomModuleService chatRoomModuleService; + private final ChattingModuleService chattingModuleService; + private final UserChatRoomModuleService userChatRoomModuleService; + private final TimeUtils timeUtils; + + @Transactional + public ReadChatRoomResponse readChatRooms(Long userId, Long spaceId) { + ChatRooms chatRooms = ChatRooms.of(chatRoomModuleService.findChatRooms(userId, spaceId)); + + List chatRoomResponses = chatRooms.toChatRoomResponses( + userId, + this::getLastMsgInfo, + (Long, chatRoom) -> calculateUnreadMsgCount(userId, chatRoom.getId(), + getLastMsgInfo(chatRoom).getLastUpdateTime()) + ); + + return ReadChatRoomResponse.of(chatRoomResponses); + } + + @Transactional + public CreateChatRoomResponse createChatRoom(Long userId, Long spaceId, CreateChatRoomRequest createChatRoomRequest, + String chatRoomImgUrl) { + User chatRoomOwner = userUtils.findUserByUserId(userId); + Space space = spaceUtils.findSpaceBySpaceId(spaceId); + + ChatRoom chatRoom = chatRoomModuleService.save( + ChatRoom.of(space, createChatRoomRequest.getName(), chatRoomImgUrl)); + saveUserChatRooms(createChatRoomRequest, chatRoom, chatRoomOwner); + + return CreateChatRoomResponse.of(chatRoom.getId()); + } + + @Transactional + public ReadChatRoomMemberResponse readChatRoomMembers(Long spaceId, Long chatRoomId) { + List userList = getUserInChatRoom(spaceId, chatRoomId); + return ReadChatRoomMemberResponse.of(userList); + } + + @Transactional + public ChatSuccessResponse updateLastReadTime(Long userId, Long chatRoomId) { + User user = userUtils.findUserByUserId(userId); + ChatRoom chatRoom = chatRoomModuleService.findChatRoom(chatRoomId); + UserChatRoom targetChatRoom = userChatRoomModuleService.findUserChatRoom(user, chatRoom); + + targetChatRoom.setLastReadTime(LocalDateTime.now()); + userChatRoomModuleService.save(targetChatRoom); + log.info("userId: " + userId + " socket disconnect 시 마지막으로 읽은 시간: " + targetChatRoom.getLastReadTime()); + + return ChatSuccessResponse.of(true); + } + + @Transactional + public ChatSuccessResponse joinChatRoom(Long chatRoomId, JoinChatRoomRequest joinChatRoomRequest) { + ChatRoom chatRoomByChatRoomId = chatRoomModuleService.findChatRoom(chatRoomId); + List memberIdList = joinChatRoomRequest.getMemberList(); + + handleJoinChatRoom(memberIdList, chatRoomByChatRoomId); + + return ChatSuccessResponse.of(true); + } + + @Transactional + public ChatSuccessResponse modifyChatRoomName(Long chatRoomId, String name) { + ChatRoom chatRoomByChatRoomId = chatRoomModuleService.findChatRoom(chatRoomId); + + chatRoomByChatRoomId.updateName(name); + chatRoomModuleService.save(chatRoomByChatRoomId); + + return ChatSuccessResponse.of(true); + } + + @Transactional + public ChatSuccessResponse exitChatRoom(Long userId, Long chatRoomId) { + User user = userUtils.findUserByUserId(userId); + ChatRoom chatRoom = chatRoomModuleService.findChatRoom(chatRoomId); + UserChatRoom userChatRoom = userChatRoomModuleService.findUserChatRoom(user, chatRoom); + + userChatRoom.updateInactive(); + userChatRoomModuleService.save(userChatRoom); + + return ChatSuccessResponse.of(true); + } + + @Transactional + public ChatSuccessResponse deleteChatRoom(Long chatRoomId) { + ChatRoom chatRoomByChatRoomId = chatRoomModuleService.findChatRoom(chatRoomId); + + chatRoomByChatRoomId.updateInactive(); + chatRoomModuleService.save(chatRoomByChatRoomId); + + return ChatSuccessResponse.of(true); + } + + private LastMessageInfoDto getLastMsgInfo(ChatRoom chatRoom) { + ChatMessage lastMsg = chattingModuleService.findMostRecentMessage(chatRoom); + LocalDateTime lastUpdateTime = lastMsg.getCreatedAt(); + HashMap lastContent = lastMsg.getContent(); + + log.info("마지막으로 업데이트된 시간: " + lastUpdateTime + " 마지막으로 읽은 내용 : " + lastContent); + + return LastMessageInfoDto.of(lastUpdateTime, lastContent); + } + + private int calculateUnreadMsgCount(Long userId, Long chatRoomId, LocalDateTime lastUpdateTime) { + User user = userUtils.findUserByUserId(userId); + ChatRoom chatRoom = chatRoomModuleService.findChatRoom(chatRoomId); + UserChatRoom userChatRoom = userChatRoomModuleService.findUserChatRoom(user, chatRoom); + + LocalDateTime lastReadTime = timeUtils.getEncodedTime(Objects.requireNonNull(userChatRoom.getLastReadTime())); + log.info("마지막으로 읽은 시간: " + lastReadTime); + + int unreadMsgCount = chattingModuleService.countUnreadMessages(chatRoom.getId(), lastReadTime, lastUpdateTime); + log.info("안읽은 메시지 개수: " + unreadMsgCount); + + return unreadMsgCount; + } + + private void saveUserChatRooms(CreateChatRoomRequest createChatRoomRequest, ChatRoom chatRoom, User chatRoomOwner) { + userChatRoomModuleService.save(UserChatRoom.of(chatRoom, chatRoomOwner, LocalDateTime.now())); + for (Long id : createChatRoomRequest.getMemberList()) { + User chatRoomMember = userUtils.findUserByUserId(id); + userChatRoomModuleService.save(UserChatRoom.of(chatRoom, chatRoomMember, LocalDateTime.now())); + } + } + + private List getUserInChatRoom(Long spaceId, Long chatRoomId) { + ChatRoom chatRoom = chatRoomModuleService.findChatRoom(chatRoomId); + UserChatRooms userChatRooms = UserChatRooms.of( + userChatRoomModuleService.findUserChatRooms(chatRoom)); + + return userChatRooms.getUsers().stream() + .map(user -> { + UserSpace userSpace = userSpaceUtils.isUserInSpace(user.getUserId(), spaceId) + .orElseThrow(() -> new CustomException(USER_IS_NOT_IN_SPACE)); + + return new UserInfoInSpace(user.getUserId(), userSpace.getUserName(), userSpace.getUserProfileImg(), + userSpace.getUserSpaceAuth()); + }) + .toList(); + } + + private void handleJoinChatRoom(List memberIdList, ChatRoom chatRoom) { + for (Long userId : Objects.requireNonNull(memberIdList)) { + User userByUserId = userUtils.findUserByUserId(userId); + + if (isUserInChatRoom(userId, chatRoom.getId())) { + if (userByUserId.getStatus().equals(BaseStatusType.INACTIVE)) { + updateAsActive(chatRoom, userByUserId); + continue; + } + throw new CustomException(USER_IS_ALREADY_IN_CHATROOM); + } + + userChatRoomModuleService.save(UserChatRoom.of(chatRoom, userByUserId, LocalDateTime.now())); + } + } + + private boolean isUserInChatRoom(Long userId, Long chatRoomId) { + ChatRoom chatRoom = chatRoomModuleService.findChatRoom(chatRoomId); + UserChatRooms userChatRooms = UserChatRooms.of(userChatRoomModuleService.findUserChatRooms(chatRoom)); + return userChatRooms.isUserJoined(userId); + } + + private void updateAsActive(ChatRoom chatRoom, User user) { + UserChatRoom userChatRoom = userChatRoomModuleService.findUserChatRoom(user, chatRoom); + userChatRoom.setUserRejoin(); + userChatRoomModuleService.save(userChatRoom); + } +} diff --git a/src/main/java/space/space_spring/domain/chat/chatroom/service/module/ChatRoomModuleService.java b/src/main/java/space/space_spring/domain/chat/chatroom/service/module/ChatRoomModuleService.java new file mode 100644 index 00000000..a10a8490 --- /dev/null +++ b/src/main/java/space/space_spring/domain/chat/chatroom/service/module/ChatRoomModuleService.java @@ -0,0 +1,36 @@ +package space.space_spring.domain.chat.chatroom.service.module; + +import static space.space_spring.response.status.BaseExceptionResponseStatus.CHATROOM_NOT_EXIST; + +import jakarta.transaction.Transactional; +import java.util.List; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import space.space_spring.domain.chat.chatroom.model.ChatRoom; +import space.space_spring.domain.chat.chatroom.repository.ChatRoomRepository; +import space.space_spring.entity.enumStatus.BaseStatusType; +import space.space_spring.exception.CustomException; + +@Component +@RequiredArgsConstructor +public class ChatRoomModuleService { + + private final ChatRoomRepository chatRoomRepository; + + @Transactional + public ChatRoom findChatRoom(Long chatRoomId) { + return Optional.ofNullable(this.chatRoomRepository.findByIdAndStatus(chatRoomId, BaseStatusType.ACTIVE)) + .orElseThrow(() -> new CustomException(CHATROOM_NOT_EXIST)); + } + + @Transactional + public List findChatRooms(Long chatRoomId, Long spaceId) { + return this.chatRoomRepository.findByUserIdAndSpaceId(chatRoomId, spaceId); + } + + @Transactional + public ChatRoom save(ChatRoom chatRoom) { + return this.chatRoomRepository.save(chatRoom); + } +} diff --git a/src/main/java/space/space_spring/domain/chat/chatroom/service/module/UserChatRoomModuleService.java b/src/main/java/space/space_spring/domain/chat/chatroom/service/module/UserChatRoomModuleService.java new file mode 100644 index 00000000..b9239704 --- /dev/null +++ b/src/main/java/space/space_spring/domain/chat/chatroom/service/module/UserChatRoomModuleService.java @@ -0,0 +1,39 @@ +package space.space_spring.domain.chat.chatroom.service.module; + +import static space.space_spring.response.status.BaseExceptionResponseStatus.USER_IS_NOT_IN_CHATROOM; + +import jakarta.transaction.Transactional; +import java.util.List; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import space.space_spring.domain.chat.chatroom.model.ChatRoom; +import space.space_spring.domain.chat.chatroom.model.UserChatRoom; +import space.space_spring.domain.chat.chatroom.repository.UserChatRoomRepository; +import space.space_spring.domain.user.model.entity.User; +import space.space_spring.entity.enumStatus.BaseStatusType; +import space.space_spring.exception.CustomException; + +@Component +@RequiredArgsConstructor +public class UserChatRoomModuleService { + + private final UserChatRoomRepository userChatRoomRepository; + + @Transactional + public UserChatRoom findUserChatRoom(User user, ChatRoom chatRoom) { + return Optional.ofNullable( + this.userChatRoomRepository.findByUserAndChatRoomAndStatus(user, chatRoom, BaseStatusType.ACTIVE)) + .orElseThrow(() -> new CustomException(USER_IS_NOT_IN_CHATROOM)); + } + + @Transactional + public List findUserChatRooms(ChatRoom chatRoom) { + return this.userChatRoomRepository.findByChatRoomAndStatus(chatRoom, BaseStatusType.ACTIVE); + } + + @Transactional + public void save(UserChatRoom userChatRoom) { + this.userChatRoomRepository.save(userChatRoom); + } +} diff --git a/src/main/java/space/space_spring/domain/chat/chatting/controller/ChattingController.java b/src/main/java/space/space_spring/domain/chat/chatting/controller/ChattingController.java new file mode 100644 index 00000000..c09083c3 --- /dev/null +++ b/src/main/java/space/space_spring/domain/chat/chatting/controller/ChattingController.java @@ -0,0 +1,42 @@ +package space.space_spring.domain.chat.chatting.controller; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.messaging.handler.annotation.*; +import org.springframework.messaging.simp.annotation.SubscribeMapping; +import org.springframework.web.bind.annotation.RestController; +import space.space_spring.argumentResolver.userSpace.CheckUserSpace; +import space.space_spring.domain.chat.chatting.model.request.ChatMessageRequest; +import space.space_spring.domain.chat.chatting.model.response.ChatMessageLogResponse; +import space.space_spring.domain.chat.chatting.model.response.ChatMessageResponse; +import space.space_spring.domain.chat.chatting.service.component.ChattingService; + +import java.io.IOException; +import java.util.Map; + +@Slf4j +@RestController +@RequiredArgsConstructor +public class ChattingController { + + private final ChattingService chattingService; + + + @MessageMapping("/chat/{chatRoomId}") + @SendTo("/topic/chat/{chatRoomId}") + @CheckUserSpace(required = false) + public ChatMessageResponse sendChatMessage (@Payload ChatMessageRequest chatMessageRequest, @DestinationVariable Long chatRoomId, + @Header("simpSessionAttributes") Map sessionAttributes) throws IOException { + Long senderId = (Long) sessionAttributes.get("userId"); + + return chattingService.sendChatMessage(senderId, chatMessageRequest, chatRoomId); + } + + @SubscribeMapping("/chat/{chatRoomId}") + @CheckUserSpace(required = false) + public ChatMessageLogResponse subscribeChatRoom (@DestinationVariable Long chatRoomId, @Header("simpSessionAttributes") Map sessionAttributes) { + sessionAttributes.put("chatRoomId", chatRoomId); + return chattingService.readChatMessageLog(chatRoomId); + } + +} diff --git a/src/main/java/space/space_spring/domain/chat/chatting/model/ChatMessages.java b/src/main/java/space/space_spring/domain/chat/chatting/model/ChatMessages.java new file mode 100644 index 00000000..50137feb --- /dev/null +++ b/src/main/java/space/space_spring/domain/chat/chatting/model/ChatMessages.java @@ -0,0 +1,26 @@ +package space.space_spring.domain.chat.chatting.model; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import space.space_spring.domain.chat.chatting.model.document.ChatMessage; +import space.space_spring.domain.chat.chatting.model.response.ChatMessageResponse; + +public class ChatMessages { + + private final List chatMessages; + + private ChatMessages(List chatMessages) { + this.chatMessages = Collections.unmodifiableList(chatMessages); + } + + public static ChatMessages of(List chatMessages) { + return new ChatMessages(chatMessages); + } + + public List toChatMessageResponses() { + return chatMessages.stream() + .map(ChatMessageResponse::create) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/space/space_spring/entity/document/ChatMessage.java b/src/main/java/space/space_spring/domain/chat/chatting/model/document/ChatMessage.java similarity index 54% rename from src/main/java/space/space_spring/entity/document/ChatMessage.java rename to src/main/java/space/space_spring/domain/chat/chatting/model/document/ChatMessage.java index 00643a0c..c9797d84 100644 --- a/src/main/java/space/space_spring/entity/document/ChatMessage.java +++ b/src/main/java/space/space_spring/domain/chat/chatting/model/document/ChatMessage.java @@ -1,10 +1,11 @@ -package space.space_spring.entity.document; +package space.space_spring.domain.chat.chatting.model.document; import lombok.Builder; import lombok.Getter; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.TypeAlias; import org.springframework.data.mongodb.core.mapping.Document; +import space.space_spring.entity.enumStatus.BaseStatusType; import space.space_spring.entity.enumStatus.ChatMessageType; import java.time.LocalDateTime; @@ -13,7 +14,6 @@ @Document(collection = "chat_message") @Getter -@Builder @TypeAlias("ChatMessage") public class ChatMessage { @Id @@ -35,7 +35,25 @@ public class ChatMessage { private LocalDateTime createdAt; - public static ChatMessage of(HashMap content, Long chatRoomId, Long spaceId, Long senderId, String senderName, String senderImg, ChatMessageType messageType) { + private BaseStatusType status; + + @Builder + private ChatMessage(String id, HashMap content, Long chatRoomId, Long spaceId, Long senderId, + String senderName, String senderImg, ChatMessageType messageType, LocalDateTime createdAt) { + this.id = id; + this.content = content; + this.chatRoomId = chatRoomId; + this.spaceId = spaceId; + this.senderId = senderId; + this.senderName = senderName; + this.senderImg = senderImg; + this.messageType = messageType; + this.createdAt = createdAt; + this.status = BaseStatusType.ACTIVE; + } + + public static ChatMessage create(HashMap content, Long chatRoomId, Long spaceId, Long senderId, + String senderName, String senderImg, ChatMessageType messageType) { return ChatMessage.builder() .content(content) .chatRoomId(chatRoomId) diff --git a/src/main/java/space/space_spring/dto/chat/request/ChatMessageRequest.java b/src/main/java/space/space_spring/domain/chat/chatting/model/request/ChatMessageRequest.java similarity index 86% rename from src/main/java/space/space_spring/dto/chat/request/ChatMessageRequest.java rename to src/main/java/space/space_spring/domain/chat/chatting/model/request/ChatMessageRequest.java index 423dce12..9a9b3f52 100644 --- a/src/main/java/space/space_spring/dto/chat/request/ChatMessageRequest.java +++ b/src/main/java/space/space_spring/domain/chat/chatting/model/request/ChatMessageRequest.java @@ -1,16 +1,14 @@ -package space.space_spring.dto.chat.request; +package space.space_spring.domain.chat.chatting.model.request; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import lombok.Getter; -import lombok.NoArgsConstructor; import space.space_spring.entity.enumStatus.ChatMessageType; import java.util.HashMap; @Getter -@NoArgsConstructor public class ChatMessageRequest { @Size(min=1, message = "메시지 내용은 공백일 수 없습니다.") diff --git a/src/main/java/space/space_spring/dto/chat/response/ChatMessageLogResponse.java b/src/main/java/space/space_spring/domain/chat/chatting/model/response/ChatMessageLogResponse.java similarity index 59% rename from src/main/java/space/space_spring/dto/chat/response/ChatMessageLogResponse.java rename to src/main/java/space/space_spring/domain/chat/chatting/model/response/ChatMessageLogResponse.java index 29f60a91..59232047 100644 --- a/src/main/java/space/space_spring/dto/chat/response/ChatMessageLogResponse.java +++ b/src/main/java/space/space_spring/domain/chat/chatting/model/response/ChatMessageLogResponse.java @@ -1,15 +1,21 @@ -package space.space_spring.dto.chat.response; +package space.space_spring.domain.chat.chatting.model.response; +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import java.util.List; @Getter -@Builder public class ChatMessageLogResponse { + private List chatMessageLog; + @Builder(access = AccessLevel.PRIVATE) + private ChatMessageLogResponse(List chatMessageLog) { + this.chatMessageLog = chatMessageLog; + } + public static ChatMessageLogResponse of(List chatMessageList) { return ChatMessageLogResponse.builder() .chatMessageLog(chatMessageList) diff --git a/src/main/java/space/space_spring/dto/chat/response/ChatMessageResponse.java b/src/main/java/space/space_spring/domain/chat/chatting/model/response/ChatMessageResponse.java similarity index 53% rename from src/main/java/space/space_spring/dto/chat/response/ChatMessageResponse.java rename to src/main/java/space/space_spring/domain/chat/chatting/model/response/ChatMessageResponse.java index 1e283d4c..95650d7b 100644 --- a/src/main/java/space/space_spring/dto/chat/response/ChatMessageResponse.java +++ b/src/main/java/space/space_spring/domain/chat/chatting/model/response/ChatMessageResponse.java @@ -1,17 +1,15 @@ -package space.space_spring.dto.chat.response; +package space.space_spring.domain.chat.chatting.model.response; -import lombok.AllArgsConstructor; +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; -import space.space_spring.entity.document.ChatMessage; +import space.space_spring.domain.chat.chatting.model.document.ChatMessage; import space.space_spring.entity.enumStatus.ChatMessageType; import java.util.HashMap; -@Builder @Getter -@AllArgsConstructor public class ChatMessageResponse { private HashMap content; @@ -26,7 +24,18 @@ public class ChatMessageResponse { private String senderImg; - public static ChatMessageResponse of(ChatMessage chatMessage) { + @Builder(access = AccessLevel.PRIVATE) + private ChatMessageResponse(HashMap content, String createdAt, ChatMessageType messageType, + Long senderId, String senderName, String senderImg) { + this.content = content; + this.createdAt = createdAt; + this.messageType = messageType; + this.senderId = senderId; + this.senderName = senderName; + this.senderImg = senderImg; + } + + public static ChatMessageResponse create(ChatMessage chatMessage) { return ChatMessageResponse.builder() .content(chatMessage.getContent()) .createdAt(String.valueOf(chatMessage.getCreatedAt())) diff --git a/src/main/java/space/space_spring/domain/chat/chatting/repository/ChattingRepository.java b/src/main/java/space/space_spring/domain/chat/chatting/repository/ChattingRepository.java new file mode 100644 index 00000000..6da67b92 --- /dev/null +++ b/src/main/java/space/space_spring/domain/chat/chatting/repository/ChattingRepository.java @@ -0,0 +1,18 @@ +package space.space_spring.domain.chat.chatting.repository; + +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.stereotype.Repository; +import space.space_spring.domain.chat.chatting.model.document.ChatMessage; + +import java.time.LocalDateTime; +import java.util.List; +import space.space_spring.entity.enumStatus.BaseStatusType; + +@Repository +public interface ChattingRepository extends MongoRepository { + List findByChatRoomIdAndStatus(Long chatRoomId, BaseStatusType status); + + ChatMessage findTopByChatRoomIdAndStatusOrderByCreatedAtDesc(Long chatRoomId, BaseStatusType status); + + int countByChatRoomIdAndStatusAndCreatedAtBetween(Long chatRoomId, BaseStatusType status, LocalDateTime lastReadTime, LocalDateTime lastUpdateTime); +} diff --git a/src/main/java/space/space_spring/domain/chat/chatting/service/component/ChattingService.java b/src/main/java/space/space_spring/domain/chat/chatting/service/component/ChattingService.java new file mode 100644 index 00000000..d2e8915e --- /dev/null +++ b/src/main/java/space/space_spring/domain/chat/chatting/service/component/ChattingService.java @@ -0,0 +1,105 @@ +package space.space_spring.domain.chat.chatting.service.component; + +import jakarta.transaction.Transactional; +import java.util.HashMap; +import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.springframework.stereotype.Service; +import space.space_spring.domain.chat.chatting.model.ChatMessages; +import space.space_spring.domain.chat.chatting.model.request.ChatMessageRequest; +import space.space_spring.domain.chat.chatting.model.response.ChatMessageLogResponse; +import space.space_spring.domain.chat.chatting.model.response.ChatMessageResponse; +import space.space_spring.domain.chat.chatting.service.module.ChattingModuleService; +import space.space_spring.domain.chat.chatting.model.document.ChatMessage; +import space.space_spring.domain.userSpace.model.entity.UserSpace; +import space.space_spring.exception.CustomException; +import space.space_spring.service.S3Uploader; +import space.space_spring.util.userSpace.UserSpaceUtils; + +import java.io.IOException; + +import static space.space_spring.response.status.BaseExceptionResponseStatus.USER_IS_NOT_IN_SPACE; + + +@Service +@RequiredArgsConstructor +public class ChattingService { + + private final S3Uploader s3Uploader; + private final UserSpaceUtils userSpaceUtils; + // isUserInSpace -> common module service + + private final ChattingModuleService chattingModuleService; + + private final static String TYPE_IMAGE = "image"; + private final static String TYPE_FILE = "file"; + private final static String IMAGE_DIR_NAME = "chattingImg"; + private final static String FILE_DIR_NAME = "chattingFile"; + + @Transactional + public ChatMessageResponse sendChatMessage(Long senderId, ChatMessageRequest chatMessageRequest, Long chatRoomId) + throws IOException { + UserSpace senderInSpace = userSpaceUtils.isUserInSpace(senderId, chatMessageRequest.getSpaceId()) + .orElseThrow(() -> new CustomException(USER_IS_NOT_IN_SPACE)); + + saveFileUrl(chatMessageRequest); + + ChatMessage message = saveChatMessage(chatMessageRequest, chatRoomId, senderInSpace); + + return ChatMessageResponse.create(message); + } + + public ChatMessageLogResponse readChatMessageLog(Long chatRoomId) { + ChatMessages chatMessages = ChatMessages.of(chattingModuleService.findChatRooms(chatRoomId)); + return ChatMessageLogResponse.of(chatMessages.toChatMessageResponses()); + } + + private void saveFileUrl(ChatMessageRequest chatMessageRequest) throws IOException { + String fileUrl = createFileUrl(chatMessageRequest); + setFileUrl(chatMessageRequest, fileUrl); + } + + private String createFileUrl(ChatMessageRequest chatMessageRequest) throws IOException { + HashMap chatMessageContent = chatMessageRequest.getContent(); + + String base64File = "", dirName = "", fileName = ""; + switch (chatMessageRequest.getMessageType()) { + case IMG -> { + base64File = chatMessageContent.get(TYPE_IMAGE); + dirName = IMAGE_DIR_NAME; + fileName = "img"; + } + case FILE -> { + base64File = chatMessageContent.get(TYPE_FILE); + dirName = FILE_DIR_NAME; + fileName = chatMessageContent.get("fileName"); + } + default -> { + } + } + + return s3Uploader.uploadBase64File(base64File, dirName, fileName); + } + + private static void setFileUrl(ChatMessageRequest chatMessageRequest, String s3Url) { + if (!s3Url.isEmpty()) { + switch (chatMessageRequest.getMessageType()) { + case IMG -> chatMessageRequest.getContent().put(TYPE_IMAGE, s3Url); + case FILE -> chatMessageRequest.getContent().put(TYPE_FILE, s3Url); + } + } + } + + @NotNull + private ChatMessage saveChatMessage(ChatMessageRequest chatMessageRequest, Long chatRoomId, UserSpace sender) { + return chattingModuleService.save(ChatMessage.create( + chatMessageRequest.getContent(), + chatRoomId, + chatMessageRequest.getSpaceId(), + sender.getUser().getUserId(), + sender.getUserName(), + sender.getUserProfileImg(), + chatMessageRequest.getMessageType() + )); + } +} diff --git a/src/main/java/space/space_spring/domain/chat/chatting/service/module/ChattingModuleService.java b/src/main/java/space/space_spring/domain/chat/chatting/service/module/ChattingModuleService.java new file mode 100644 index 00000000..51628273 --- /dev/null +++ b/src/main/java/space/space_spring/domain/chat/chatting/service/module/ChattingModuleService.java @@ -0,0 +1,54 @@ +package space.space_spring.domain.chat.chatting.service.module; + +import jakarta.transaction.Transactional; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import space.space_spring.domain.chat.chatroom.model.ChatRoom; +import space.space_spring.domain.chat.chatting.model.document.ChatMessage; +import space.space_spring.domain.chat.chatting.repository.ChattingRepository; +import space.space_spring.entity.enumStatus.BaseStatusType; +import space.space_spring.global.util.TimeUtils; + +@Component +@RequiredArgsConstructor +public class ChattingModuleService { + + private final ChattingRepository chattingRepository; + private final TimeUtils timeUtils; + + @Transactional + public ChatMessage findMostRecentMessage(ChatRoom chatRoom) { + return Optional.ofNullable( + this.chattingRepository.findTopByChatRoomIdAndStatusOrderByCreatedAtDesc(chatRoom.getId(), + BaseStatusType.ACTIVE)) + .orElseGet(() -> ChatMessage.builder() + .createdAt(timeUtils.getEncodedTime(chatRoom.getCreatedAt())) + .content(new HashMap<>(Map.of("text", "메시지를 전송해보세요"))) + .build()); + } + + @Transactional + public List findChatRooms(Long chatRoomId) { + return this.chattingRepository.findByChatRoomIdAndStatus(chatRoomId, BaseStatusType.ACTIVE); + } + + @Transactional + public ChatMessage save(ChatMessage chatMessage) { + return this.chattingRepository.save(chatMessage); + } + + @Transactional + public int countUnreadMessages(Long chatRoomId, LocalDateTime lastReadTime, LocalDateTime lastUpdateTime) { + return this.chattingRepository.countByChatRoomIdAndStatusAndCreatedAtBetween( + chatRoomId, + BaseStatusType.ACTIVE, + lastReadTime, + lastUpdateTime); + } + +} diff --git a/src/main/java/space/space_spring/dto/chat/dto/LastMessageInfoDto.java b/src/main/java/space/space_spring/dto/chat/dto/LastMessageInfoDto.java deleted file mode 100644 index 70a54286..00000000 --- a/src/main/java/space/space_spring/dto/chat/dto/LastMessageInfoDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package space.space_spring.dto.chat.dto; - -import lombok.Builder; -import lombok.Getter; - -import java.time.LocalDateTime; -import java.util.HashMap; - -@Getter -@Builder -public class LastMessageInfoDto { - - private LocalDateTime lastUpdateTime; - - private HashMap lastContent; -} - diff --git a/src/main/java/space/space_spring/dto/chat/response/ChatRoomResponse.java b/src/main/java/space/space_spring/dto/chat/response/ChatRoomResponse.java deleted file mode 100644 index 7f016870..00000000 --- a/src/main/java/space/space_spring/dto/chat/response/ChatRoomResponse.java +++ /dev/null @@ -1,36 +0,0 @@ -package space.space_spring.dto.chat.response; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import space.space_spring.entity.ChatRoom; - -import java.util.HashMap; - -@Builder -@Getter -@AllArgsConstructor -public class ChatRoomResponse { - private Long id; - - private String name; - - private String imgUrl; - - private HashMap lastMsg; - - private String lastTime; - - private int unreadMsgCount; - - public static ChatRoomResponse of(ChatRoom chatRoom, HashMap lastMsg, String lastTime, int unreadMsgCount) { - return ChatRoomResponse.builder() - .id(chatRoom.getId()) - .name(chatRoom.getName()) - .imgUrl(chatRoom.getImg()) - .lastMsg(lastMsg) - .lastTime(lastTime) - .unreadMsgCount(unreadMsgCount) - .build(); - } -} diff --git a/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java b/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java index 62dc1749..00dad0a3 100644 --- a/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java +++ b/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java @@ -86,7 +86,8 @@ public enum BaseExceptionResponseStatus implements ResponseStatus { CHATROOM_NOT_EXIST(8001, HttpStatus.NOT_FOUND, "존재하지 않는 채팅방입니다."), INVALID_CHATROOM_JOIN(8001, HttpStatus.BAD_REQUEST, "채팅방 멤버 초대 요청에서 잘못된 값이 존재합니다."), BASE64_CONVERT_FAIL_IN_MEMORY(8002, HttpStatus.INTERNAL_SERVER_ERROR, "base64 파일 변환 과정에서 문제가 생겼습니다."), - USER_IS_ALREADY_IN_CHAT_ROOM(8003, HttpStatus.BAD_REQUEST, "해당 채팅방에 이미 초대된 멤버가 포함되어 있습니다."), + USER_IS_ALREADY_IN_CHATROOM(8003, HttpStatus.BAD_REQUEST, "해당 채팅방에 이미 초대된 멤버가 포함되어 있습니다."), + USER_IS_NOT_IN_CHATROOM(8004, HttpStatus.NOT_FOUND, "해당 유저는 해당 채팅방에 참여하고 있지 않습니다."), /** * 9000 : MultipartFile 오류 diff --git a/src/main/java/space/space_spring/service/ChatRoomService.java b/src/main/java/space/space_spring/service/ChatRoomService.java deleted file mode 100644 index ce59d85f..00000000 --- a/src/main/java/space/space_spring/service/ChatRoomService.java +++ /dev/null @@ -1,266 +0,0 @@ -package space.space_spring.service; - -import jakarta.transaction.Transactional; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import space.space_spring.domain.userSpace.model.entity.UserSpace; -import space.space_spring.domain.userSpace.repository.UserSpaceDao; -import space.space_spring.dao.chat.ChatRoomRepository; -import space.space_spring.dao.chat.ChattingRepository; -import space.space_spring.dao.chat.UserChatRoomRepository; -import space.space_spring.domain.space.model.entity.Space; -import space.space_spring.domain.user.model.entity.User; -import space.space_spring.dto.chat.dto.LastMessageInfoDto; -import space.space_spring.dto.chat.request.JoinChatRoomRequest; -import space.space_spring.dto.chat.response.*; -import space.space_spring.dto.chat.request.CreateChatRoomRequest; -import space.space_spring.domain.userSpace.model.UserInfoInSpace; -import space.space_spring.entity.*; -import space.space_spring.entity.document.ChatMessage; - -import space.space_spring.entity.enumStatus.BaseStatusType; -import space.space_spring.exception.CustomException; -import space.space_spring.global.util.TimeUtils; -import space.space_spring.util.space.SpaceUtils; -import space.space_spring.util.user.UserUtils; - -import java.time.LocalDateTime; -import java.util.*; - -import static space.space_spring.response.status.BaseExceptionResponseStatus.*; - -@Service -@Slf4j -@RequiredArgsConstructor -public class ChatRoomService { - - private final UserUtils userUtils; - private final SpaceUtils spaceUtils; - private final TimeUtils timeUtils; - private final UserSpaceDao userSpaceDao; - private final ChattingRepository chattingRepository; - private final ChatRoomRepository chatRoomRepository; - private final UserChatRoomRepository userChatRoomRepository; - - @Transactional - public ReadChatRoomResponse readChatRooms(Long userId, Long spaceId) { - // TODO 1: userId에 해당하는 user find - User userByUserId = userUtils.findUserByUserId(userId); - - // TODO 2: spaceId에 해당하는 space find - Space spaceBySpaceId = spaceUtils.findSpaceBySpaceId(spaceId); - - // TODO 3: 해당 user의 해당 space 내의 채팅방 리스트 return - List chatRoomList = chatRoomRepository.findByUserAndSpace(userByUserId, spaceBySpaceId); - - return ReadChatRoomResponse.of(chatRoomList.stream() - .map(cr -> { - // TODO 4: 각 채팅방의 마지막으로 업데이트된 메시지 정보 find - LastMessageInfoDto lastMsgInfo = getLastMsgInfo(cr); - LocalDateTime lastUpdateTime = lastMsgInfo.getLastUpdateTime(); - HashMap lastContent = lastMsgInfo.getLastContent(); - - // TODO 5: userChatRoom의 안읽은 메시지 개수 계산 - int unreadMsgCount = calculateUnreadMsgCount(userByUserId, cr, lastUpdateTime); - - return ChatRoomResponse.of(cr, lastContent, String.valueOf(lastUpdateTime), unreadMsgCount); - }) - .filter(Objects::nonNull) // null 값을 제거 - .toList() - ); - } - - @Transactional - public CreateChatRoomResponse createChatRoom(Long userId, Long spaceId, CreateChatRoomRequest createChatRoomRequest, String chatRoomImgUrl) { - // TODO 1: userId에 해당하는 user find - User userByUserId = userUtils.findUserByUserId(userId); - - // TODO 2: spaceId에 해당하는 space find - Space spaceBySpaceId = spaceUtils.findSpaceBySpaceId(spaceId); - - // TODO 3: chatRoom 생성 및 저장 - ChatRoom chatRoom = chatRoomRepository.save(ChatRoom.of(spaceBySpaceId, createChatRoomRequest.getName(), chatRoomImgUrl)); - - // TODO 4: userChatRoom 매핑 정보 저장 - userChatRoomRepository.save(UserChatRoom.of(chatRoom, userByUserId, LocalDateTime.now())); - for (Long id : createChatRoomRequest.getMemberList()) { - User user = userUtils.findUserByUserId(id); - userChatRoomRepository.save(UserChatRoom.of(chatRoom, user, LocalDateTime.now())); - } - - // TODO 5: chatroom id 반환 - return CreateChatRoomResponse.of(chatRoom.getId()); - } - - @Transactional - public ReadChatRoomMemberResponse readChatRoomMembers(Long spaceId, Long chatRoomId) { - - // TODO 1: spaceId에 해당하는 space find - Space spaceById = spaceUtils.findSpaceBySpaceId(spaceId); - - // TODO 2: chatRoomId에 해당하는 chatRoom find - ChatRoom chatRoomByChatRoomId = Optional.ofNullable( - chatRoomRepository.findByIdAndStatus(chatRoomId, BaseStatusType.ACTIVE)) - .orElseThrow(() -> new CustomException(CHATROOM_NOT_EXIST)); - - // TODO 3: 해당 userChatRoom의 user들 find - List userList = getUserInChatRoom(spaceById, chatRoomByChatRoomId); - - return ReadChatRoomMemberResponse.of(userList); - } - - @Transactional - public ChatSuccessResponse updateLastReadTime(Long userId, Long chatRoomId) { - // TODO 1: userId에 해당하는 user find - User userByUserId = userUtils.findUserByUserId(userId); - - // TODO 2: chatRoomId에 해당하는 chatRoom find - ChatRoom chatRoomByChatRoomId = Optional.ofNullable( - chatRoomRepository.findByIdAndStatus(chatRoomId, BaseStatusType.ACTIVE)) - .orElseThrow(() -> new CustomException(CHATROOM_NOT_EXIST)); - - // TODO 3: 해당 user와 chatRoom에 대한 userChatRoom find - UserChatRoom targetChatRoom = userChatRoomRepository.findByUserAndChatRoomAndStatus(userByUserId, chatRoomByChatRoomId, BaseStatusType.ACTIVE); - - // TODO 4: userChatRoom의 마지막으로 읽은 시간 저장 - targetChatRoom.setLastReadTime(LocalDateTime.now()); - userChatRoomRepository.save(targetChatRoom); - log.info("userId: " + userId + " socket disconnect 시 마지막으로 읽은 시간: " + targetChatRoom.getLastReadTime()); - - return ChatSuccessResponse.of(true); - } - - @Transactional - public ChatSuccessResponse joinChatRoom(Long chatRoomId, JoinChatRoomRequest joinChatRoomRequest) { - List memberIdList = joinChatRoomRequest.getMemberList(); - - // TODO 1: chatRoomId에 해당하는 chatRoom find - ChatRoom chatRoomByChatRoomId = Optional.ofNullable( - chatRoomRepository.findByIdAndStatus(chatRoomId, BaseStatusType.ACTIVE)) - .orElseThrow(() -> new CustomException(CHATROOM_NOT_EXIST)); - - // TODO 2: 유저들의 채팅방 초대 이력에 따른 재초대 - handleJoinChatRoom(memberIdList, chatRoomByChatRoomId); - - return ChatSuccessResponse.of(true); - } - - @Transactional - public ChatSuccessResponse modifyChatRoomName(Long chatRoomId, String name) { - // TODO 1: chatRoomId에 해당하는 chatRoom find - ChatRoom chatRoomByChatRoomId = Optional.ofNullable( - chatRoomRepository.findByIdAndStatus(chatRoomId, BaseStatusType.ACTIVE)) - .orElseThrow(() -> new CustomException(CHATROOM_NOT_EXIST)); - - // TODO 2: 채팅방 이름 변경 - chatRoomByChatRoomId.updateName(name); - chatRoomRepository.save(chatRoomByChatRoomId); - - return ChatSuccessResponse.of(true); - } - - @Transactional - public ChatSuccessResponse exitChatRoom(Long userId, Long chatRoomId) { - // TODO 1: userId에 해당하는 user find - User userByUserId = userUtils.findUserByUserId(userId); - - // TODO 2: chatRoomId에 해당하는 chatRoom find - ChatRoom chatRoomByChatRoomId = Optional.ofNullable( - chatRoomRepository.findByIdAndStatus(chatRoomId, BaseStatusType.ACTIVE)) - .orElseThrow(() -> new CustomException(CHATROOM_NOT_EXIST)); - - // TODO 3: 해당 user와 chatRoom에 대한 userChatRoom find - UserChatRoom userChatRoom = userChatRoomRepository.findByUserAndChatRoomAndStatus(userByUserId, chatRoomByChatRoomId, BaseStatusType.ACTIVE); - - // TODO 4: 해당 userChatRoom inactive로 변경 - userChatRoom.updateInactive(); - userChatRoomRepository.save(userChatRoom); - - return ChatSuccessResponse.of(true); - } - - @Transactional - public ChatSuccessResponse deleteChatRoom(Long chatRoomId) { - // TODO 1: chatRoomId에 해당하는 chatRoom find - ChatRoom chatRoomByChatRoomId = Optional.ofNullable( - chatRoomRepository.findByIdAndStatus(chatRoomId, BaseStatusType.ACTIVE)) - .orElseThrow(() -> new CustomException(CHATROOM_NOT_EXIST)); - - // TODO 2: 해당 chatRoom inactive로 변경 - chatRoomByChatRoomId.updateInactive(); - chatRoomRepository.save(chatRoomByChatRoomId); - - return ChatSuccessResponse.of(true); - } - - private boolean isUserInChatRoom(User userByUserId, ChatRoom chatRoomByChatRoomId) { - List chatRoomList = userChatRoomRepository.findByChatRoomAndStatus(chatRoomByChatRoomId, BaseStatusType.ACTIVE); - return chatRoomList.stream().anyMatch(userChatRoom -> userChatRoom.getUser().equals(userByUserId)); - } - - private LastMessageInfoDto getLastMsgInfo(ChatRoom chatRoom) { - ChatMessage lastMsg = chattingRepository.findTopByChatRoomIdOrderByCreatedAtDesc(chatRoom.getId()); - LocalDateTime lastUpdateTime = lastMsg != null ? lastMsg.getCreatedAt() :timeUtils.getEncodedTime(chatRoom.getCreatedAt()); - HashMap lastContent = lastMsg != null ? lastMsg.getContent() : new HashMap<>(Map.of("text", "메시지를 전송해보세요")); - - log.info("마지막으로 업데이트된 시간: " + lastUpdateTime + " 마지막으로 읽은 내용 : " + lastContent); - - return LastMessageInfoDto.builder().lastUpdateTime(lastUpdateTime).lastContent(lastContent).build(); - } - - private int calculateUnreadMsgCount(User userByUserId, ChatRoom chatRoom, LocalDateTime lastUpdateTime) { - UserChatRoom userChatRoom = userChatRoomRepository.findByUserAndChatRoomAndStatus(userByUserId, chatRoom, BaseStatusType.ACTIVE); - LocalDateTime lastReadTime = timeUtils.getEncodedTime(userChatRoom.getLastReadTime()); // LocalDateTime으로 변환 - log.info("마지막으로 읽은 시간: " + lastReadTime); - - int unreadMsgCount = chattingRepository.countByChatRoomIdAndCreatedAtBetween( - chatRoom.getId(), - lastReadTime, - lastUpdateTime - ); - log.info("안읽은 메시지 개수: " + unreadMsgCount); - - return unreadMsgCount; - } - - private List getUserInChatRoom(Space space, ChatRoom chatRoom) { - List userList = new ArrayList<>(); - List userChatRoomList = userChatRoomRepository.findByChatRoomAndStatus(chatRoom, BaseStatusType.ACTIVE); - - userChatRoomList.forEach(userChatRoom -> { - User user = userChatRoom.getUser(); - - // TODO 1: 스페이스 프로필 이미지 get 위해 userSpace find - UserSpace userSpace = userSpaceDao.findUserSpaceByUserAndSpace(user, space) - .orElseThrow(() -> new CustomException(USER_IS_NOT_IN_SPACE)); - - // TODO 2: user 정보 추가 - userList.add(new UserInfoInSpace(user.getUserId(), userSpace.getUserName(), userSpace.getUserProfileImg(), userSpace.getUserSpaceAuth())); - }); - - return userList; - } - - private void handleJoinChatRoom(List memberIdList, ChatRoom chatRoomByChatRoomId) { - for (Long memberId : Objects.requireNonNull(memberIdList)) { - User userByUserId = userUtils.findUserByUserId(memberId); - - // TODO 1: 유저가 채팅방에 초대된 적이 있는 경우 다시 초대 - if (isUserInChatRoom(userByUserId, chatRoomByChatRoomId)) { - // TODO 2: 유저가 채팅방에 초대되었다가 나간 경우 다시 초대 - if (userByUserId.getStatus().equals(BaseStatusType.INACTIVE)) { - UserChatRoom userChatRoom = userChatRoomRepository.findByUserAndChatRoomAndStatus(userByUserId, chatRoomByChatRoomId, BaseStatusType.ACTIVE); - userChatRoom.setUserRejoin(); - userChatRoomRepository.save(userChatRoom); - continue; - } - // TODO 3: 유저가 채팅방에 초대되어서 참가하고 있는 경우 예외 발생 - throw new CustomException(USER_IS_ALREADY_IN_CHAT_ROOM); - } - - // TODO 4: 채팅방에 초대된 적이 없는 유저에 대한 userChatRoom 테이블 생성 - userChatRoomRepository.save(UserChatRoom.of(chatRoomByChatRoomId, userByUserId, LocalDateTime.now())); - } - } -} diff --git a/src/main/java/space/space_spring/service/ChattingService.java b/src/main/java/space/space_spring/service/ChattingService.java deleted file mode 100644 index 2a83d4ad..00000000 --- a/src/main/java/space/space_spring/service/ChattingService.java +++ /dev/null @@ -1,78 +0,0 @@ -package space.space_spring.service; - -import jakarta.transaction.Transactional; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import space.space_spring.dao.chat.ChattingRepository; -import space.space_spring.dto.chat.request.ChatMessageRequest; -import space.space_spring.dto.chat.response.ChatMessageLogResponse; -import space.space_spring.dto.chat.response.ChatMessageResponse; -import space.space_spring.domain.userSpace.model.entity.UserSpace; -import space.space_spring.entity.document.ChatMessage; -import space.space_spring.entity.enumStatus.ChatMessageType; -import space.space_spring.exception.CustomException; -import space.space_spring.util.userSpace.UserSpaceUtils; - -import java.io.IOException; -import java.util.List; -import java.util.stream.Collectors; - -import static space.space_spring.response.status.BaseExceptionResponseStatus.USER_IS_NOT_IN_SPACE; - - -@Service -@RequiredArgsConstructor -public class ChattingService { - - private final S3Uploader s3Uploader; - private final UserSpaceUtils userSpaceUtils; - private final ChattingRepository chattingRepository; - - @Transactional - public ChatMessageResponse sendChatMessage(Long senderId, ChatMessageRequest chatMessageRequest, Long chatRoomId) throws IOException { - - // TODO 1: 메시지 메타데이터 저장 위해 전송자 찾기 - UserSpace senderInSpace = userSpaceUtils.isUserInSpace(senderId, chatMessageRequest.getSpaceId()) - .orElseThrow(() -> new CustomException(USER_IS_NOT_IN_SPACE)); - - // TODO 2: validation 후 전송자 이름 및 프로필 사진 get - String senderName = senderInSpace.getUserName(); - String senderProfileImg = senderInSpace.getUserProfileImg(); - - // TODO 3: 이미지 및 파일 포함하는 경우 S3 업로드 - String s3Url = switch (chatMessageRequest.getMessageType()) { - case IMG -> s3Uploader.uploadBase64File(chatMessageRequest.getContent().get("image") , "chattingImg", "img"); - case FILE -> s3Uploader.uploadBase64File(chatMessageRequest.getContent().get("file") , "chattingFile", chatMessageRequest.getContent().get("fileName")); - default -> ""; - }; - - // TODO 4: DB에 S3 url 저장 위한 content 처리 - if (!s3Url.isEmpty()) { - if (chatMessageRequest.getMessageType().equals(ChatMessageType.IMG)) { - chatMessageRequest.getContent().put("image", s3Url); - } else { - chatMessageRequest.getContent().put("file", s3Url); - } - } - - // TODO 4: DB에 메시지 저장 - ChatMessage message = chattingRepository.insert(ChatMessage.of( - chatMessageRequest.getContent(), - chatRoomId, - chatMessageRequest.getSpaceId(), - senderId, - senderName, - senderProfileImg, - chatMessageRequest.getMessageType() - )); - - return ChatMessageResponse.of(message); - } - - public ChatMessageLogResponse readChatMessageLog(Long chatRoomId) { - List chatMessageList = chattingRepository.findByChatRoomId(chatRoomId); - return ChatMessageLogResponse.of(chatMessageList.stream() - .map(ChatMessageResponse::of) - .collect(Collectors.toList())); - } -} diff --git a/src/test/java/space/space_spring/controller/ChatRoomControllerTest.java b/src/test/java/space/space_spring/controller/ChatRoomControllerTest.java deleted file mode 100644 index 91e631d1..00000000 --- a/src/test/java/space/space_spring/controller/ChatRoomControllerTest.java +++ /dev/null @@ -1,250 +0,0 @@ -package space.space_spring.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; -import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext; -import org.springframework.http.MediaType; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.test.web.servlet.MockMvc; -import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuthHandlerArgumentResolver; -import space.space_spring.argumentResolver.userSpace.UserSpaceAuthHandlerArgumentResolver; -import space.space_spring.argumentResolver.userSpace.UserSpaceIdHandlerArgumentResolver; -import space.space_spring.config.SecurityConfig; -import space.space_spring.dto.chat.request.CreateChatRoomRequest; -import space.space_spring.dto.chat.request.JoinChatRoomRequest; -import space.space_spring.dto.chat.response.*; -import space.space_spring.domain.userSpace.model.UserInfoInSpace; -import space.space_spring.interceptor.UserSpaceValidationInterceptor; -import space.space_spring.interceptor.jwtLogin.JwtLoginAuthInterceptor; -import space.space_spring.service.ChatRoomService; -import space.space_spring.service.S3Uploader; - -import java.nio.charset.StandardCharsets; -import java.util.List; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; - -@WebMvcTest(ChatRoomController.class) -@MockBean(JpaMetamodelMappingContext.class) -@Import(SecurityConfig.class) -@AutoConfigureMockMvc(addFilters = false) // security config ignore -public class ChatRoomControllerTest { - - @Autowired - private MockMvc mockMvc; - - @Autowired - private ObjectMapper objectMapper; - - @MockBean - private ChatRoomService chatRoomService; - - @MockBean - private S3Uploader s3Uploader; - - @MockBean - private JwtLoginAuthHandlerArgumentResolver jwtLoginAuthHandlerArgumentResolver; - - @MockBean - private UserSpaceIdHandlerArgumentResolver userSpaceIdHandlerArgumentResolver; - - @MockBean - private UserSpaceAuthHandlerArgumentResolver userSpaceAuthHandlerArgumentResolver; - - @MockBean - private JwtLoginAuthInterceptor jwtLoginAuthInterceptor; - - @MockBean - private UserSpaceValidationInterceptor userSpaceValidationInterceptor; - - private static Long userId; - - private static Long spaceId; - - private static Long chatRoomId; - - private static Long userSpaceId; - - private static MockMultipartFile mockImgFile; - - private ChatSuccessResponse commonResponse; - - @BeforeEach - void 채팅방_테스트_설정() throws Exception { - userId = 0L; - spaceId = 1L; - userSpaceId = 2L; - chatRoomId = 3L; - - given(userSpaceValidationInterceptor.preHandle(any(), any(), any())) - .willReturn(true); - - given(jwtLoginAuthInterceptor.preHandle(any(), any(), any())) - .willReturn(true); - - given(jwtLoginAuthHandlerArgumentResolver.resolveArgument(any(), any(), any(), any())) - .willReturn(userId); - - given(userSpaceIdHandlerArgumentResolver.resolveArgument(any(), any(), any(), any())) - .willReturn(userSpaceId); - - given(userSpaceAuthHandlerArgumentResolver.resolveArgument(any(), any(), any(), any())) - .willReturn("manager"); - - mockImgFile = new MockMultipartFile("img", "test.png", "png", "test file".getBytes(StandardCharsets.UTF_8)); - - commonResponse = ChatSuccessResponse.builder().build(); - } - - @Test - @DisplayName("모든_채팅방_조회_테스트") - void 모든_채팅방_조회_테스트() throws Exception { - // given - ReadChatRoomResponse response = ReadChatRoomResponse.of(List.of(new ChatRoomResponse[]{})); - given(chatRoomService.readChatRooms(userId, spaceId)) - .willReturn(response); - - // when & then - mockMvc.perform(get("/space/{spaceId}/chat/chatroom", spaceId)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.message").exists()); - } - - @Test - @DisplayName("채팅방_생성_테스트") - void 채팅방_생성_테스트() throws Exception { - // given -// CreateChatRoomRequest request = new CreateChatRoomRequest(); - CreateChatRoomRequest request = CreateChatRoomRequest.builder() - .name("testChatRoom") - .img(mockImgFile) - .memberList(List.of(4L)) - .build(); -// request.setName("testChatRoom"); -// request.setImg(mockImgFile); -// request.setMemberList(List.of(4L)); - - CreateChatRoomResponse response = CreateChatRoomResponse.of(chatRoomId); - given(chatRoomService.createChatRoom(userId, spaceId, request, "asdf")) - .willReturn(response); - - // when & then - mockMvc.perform(multipart("/space/{spaceId}/chat/chatroom", spaceId) - .file(mockImgFile) - .param("name", request.getName()) - .param("memberList", request.getMemberList().stream() - .map(String::valueOf) - .toArray(String[]::new)) - .param("userSpaceAuth", "manager") - .contentType(MediaType.MULTIPART_FORM_DATA)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.message").exists()); - } - - @Test - @DisplayName("특정_채팅방의_모든_유저_정보_조회_테스트") - void 특정_채팅방의_모든_유저_정보_조회_테스트() throws Exception { - // given - ReadChatRoomMemberResponse response = ReadChatRoomMemberResponse.of(List.of(new UserInfoInSpace[]{})); - given(chatRoomService.readChatRoomMembers(userId, spaceId)) - .willReturn(response); - - // when & then - mockMvc.perform(get("/space/{spaceId}/chat/{chatRoomId}/member", spaceId, chatRoomId)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.message").exists()); - } - - @Test - @DisplayName("특정_채팅방에_유저_초대_테스트") - void 특정_채팅방에_유저_초대_테스트() throws Exception { - // given - JoinChatRoomRequest request = JoinChatRoomRequest.builder().memberList(List.of(1L)).build(); - String content = objectMapper.writeValueAsString(request); - - given(chatRoomService.joinChatRoom(chatRoomId, request)) - .willReturn(commonResponse); - - // when & then - mockMvc.perform(post("/space/{spaceId}/chat/{chatRoomId}/member", spaceId, chatRoomId) - .param("userSpaceAuth", "manager") - .contentType(MediaType.APPLICATION_JSON) - .content(content)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.message").exists()); - } - - @Test - @DisplayName("특정_유저가_채팅방에서_떠난_시간_저장_테스트") - void 특정_유저가_채팅방에서_떠난_시간_저장_테스트() throws Exception { - // given - given(chatRoomService.updateLastReadTime(userId, chatRoomId)) - .willReturn(commonResponse); - - // when & then - mockMvc.perform(post("/space/{spaceId}/chat/{chatRoomId}/leave", spaceId, chatRoomId)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.message").exists()); - } - - @Test - @DisplayName("특정_채팅방의_이름_수정_테스트") - void 특정_채팅방의_이름_수정_테스트() throws Exception { - // given - given(chatRoomService.modifyChatRoomName(chatRoomId, "newChatRoom")) - .willReturn(commonResponse); - - // when & then - mockMvc.perform(post("/space/{spaceId}/chat/{chatRoomId}/setting", spaceId, chatRoomId) - .param("name", "newChatRoom") - .param("userSpaceAuth", "manager")) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.message").exists()); - } - - @Test - @DisplayName("특정_채팅방에서_나가기_테스트") - void 특정_채팅방에서_나가기_테스트() throws Exception { - // given - given(chatRoomService.exitChatRoom(userId, chatRoomId)) - .willReturn(commonResponse); - - // when & then - mockMvc.perform(post("/space/{spaceId}/chat/{chatRoomId}/exit", spaceId, chatRoomId)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.message").exists()); - } - - @Test - @DisplayName("특정_채팅방_삭제_테스트") - void 특정_채팅방_삭제_테스트() throws Exception { - // given - given(chatRoomService.deleteChatRoom(chatRoomId)) - .willReturn(commonResponse); - - // when & then - mockMvc.perform(post("/space/{spaceId}/chat/{chatRoomId}/delete", spaceId, chatRoomId) - .param("userSpaceAuth", "manager")) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.message").exists()); - } -} diff --git a/src/test/java/space/space_spring/domain/chat/chatroom/controller/ChatRoomControllerTest.java b/src/test/java/space/space_spring/domain/chat/chatroom/controller/ChatRoomControllerTest.java new file mode 100644 index 00000000..1d494a4c --- /dev/null +++ b/src/test/java/space/space_spring/domain/chat/chatroom/controller/ChatRoomControllerTest.java @@ -0,0 +1,255 @@ +//package space.space_spring.controller; +// +//import com.fasterxml.jackson.databind.ObjectMapper; +//import org.junit.jupiter.api.BeforeEach; +//import org.junit.jupiter.api.DisplayName; +//import org.junit.jupiter.api.Test; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +//import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +//import org.springframework.boot.test.mock.mockito.MockBean; +//import org.springframework.context.annotation.Import; +//import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext; +//import org.springframework.http.MediaType; +//import org.springframework.mock.web.MockMultipartFile; +//import org.springframework.test.web.servlet.MockMvc; +//import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuthHandlerArgumentResolver; +//import space.space_spring.argumentResolver.userSpace.UserSpaceAuthHandlerArgumentResolver; +//import space.space_spring.argumentResolver.userSpace.UserSpaceIdHandlerArgumentResolver; +//import space.space_spring.config.SecurityConfig; +//import space.space_spring.domain.chat.chatroom.controller.ChatRoomController; +//import space.space_spring.domain.chat.chatroom.model.request.CreateChatRoomRequest; +//import space.space_spring.domain.chat.chatroom.model.request.JoinChatRoomRequest; +//import space.space_spring.domain.chat.chatroom.model.response.ChatRoomResponse; +//import space.space_spring.domain.chat.chatroom.model.response.ChatSuccessResponse; +//import space.space_spring.domain.chat.chatroom.model.response.CreateChatRoomResponse; +//import space.space_spring.domain.chat.chatroom.model.response.ReadChatRoomMemberResponse; +//import space.space_spring.domain.chat.chatroom.model.response.ReadChatRoomResponse; +//import space.space_spring.dto.userSpace.UserInfoInSpace; +//import space.space_spring.interceptor.UserSpaceValidationInterceptor; +//import space.space_spring.interceptor.jwtLogin.JwtLoginAuthInterceptor; +//import space.space_spring.domain.chat.chatroom.service.component.ChatRoomService; +//import space.space_spring.service.S3Uploader; +// +//import java.nio.charset.StandardCharsets; +//import java.util.List; +// +//import static org.mockito.ArgumentMatchers.any; +//import static org.mockito.BDDMockito.given; +//import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +//import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +//import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +// +//@WebMvcTest(ChatRoomController.class) +//@MockBean(JpaMetamodelMappingContext.class) +//@Import(SecurityConfig.class) +//@AutoConfigureMockMvc(addFilters = false) // security config ignore +//public class ChatRoomControllerTest { +// +// @Autowired +// private MockMvc mockMvc; +// +// @Autowired +// private ObjectMapper objectMapper; +// +// @MockBean +// private ChatRoomService chatRoomService; +// +// @MockBean +// private S3Uploader s3Uploader; +// +// @MockBean +// private JwtLoginAuthHandlerArgumentResolver jwtLoginAuthHandlerArgumentResolver; +// +// @MockBean +// private UserSpaceIdHandlerArgumentResolver userSpaceIdHandlerArgumentResolver; +// +// @MockBean +// private UserSpaceAuthHandlerArgumentResolver userSpaceAuthHandlerArgumentResolver; +// +// @MockBean +// private JwtLoginAuthInterceptor jwtLoginAuthInterceptor; +// +// @MockBean +// private UserSpaceValidationInterceptor userSpaceValidationInterceptor; +// +// private static Long userId; +// +// private static Long spaceId; +// +// private static Long chatRoomId; +// +// private static Long userSpaceId; +// +// private static MockMultipartFile mockImgFile; +// +// private ChatSuccessResponse commonResponse; +// +// @BeforeEach +// void 채팅방_테스트_설정() throws Exception { +// userId = 0L; +// spaceId = 1L; +// userSpaceId = 2L; +// chatRoomId = 3L; +// +// given(userSpaceValidationInterceptor.preHandle(any(), any(), any())) +// .willReturn(true); +// +// given(jwtLoginAuthInterceptor.preHandle(any(), any(), any())) +// .willReturn(true); +// +// given(jwtLoginAuthHandlerArgumentResolver.resolveArgument(any(), any(), any(), any())) +// .willReturn(userId); +// +// given(userSpaceIdHandlerArgumentResolver.resolveArgument(any(), any(), any(), any())) +// .willReturn(userSpaceId); +// +// given(userSpaceAuthHandlerArgumentResolver.resolveArgument(any(), any(), any(), any())) +// .willReturn("manager"); +// +// mockImgFile = new MockMultipartFile("img", "test.png", "png", "test file".getBytes(StandardCharsets.UTF_8)); +// +// commonResponse = ChatSuccessResponse.builder().build(); +// } +// +// @Test +// @DisplayName("모든_채팅방_조회_테스트") +// void 모든_채팅방_조회_테스트() throws Exception { +// // given +// ReadChatRoomResponse response = ReadChatRoomResponse.of(List.of(new ChatRoomResponse[]{})); +// given(chatRoomService.readChatRooms(userId, spaceId)) +// .willReturn(response); +// +// // when & then +// mockMvc.perform(get("/space/{spaceId}/chat/chatroom", spaceId)) +// .andDo(print()) +// .andExpect(status().isOk()) +// .andExpect(jsonPath("$.message").exists()); +// } +// +// @Test +// @DisplayName("채팅방_생성_테스트") +// void 채팅방_생성_테스트() throws Exception { +// // given +//// CreateChatRoomRequest request = new CreateChatRoomRequest(); +// CreateChatRoomRequest request = CreateChatRoomRequest.builder() +// .name("testChatRoom") +// .img(mockImgFile) +// .memberList(List.of(4L)) +// .build(); +//// request.setName("testChatRoom"); +//// request.setImg(mockImgFile); +//// request.setMemberList(List.of(4L)); +// +// CreateChatRoomResponse response = CreateChatRoomResponse.of(chatRoomId); +// given(chatRoomService.createChatRoom(userId, spaceId, request, "asdf")) +// .willReturn(response); +// +// // when & then +// mockMvc.perform(multipart("/space/{spaceId}/chat/chatroom", spaceId) +// .file(mockImgFile) +// .param("name", request.getName()) +// .param("memberList", request.getMemberList().stream() +// .map(String::valueOf) +// .toArray(String[]::new)) +// .param("userSpaceAuth", "manager") +// .contentType(MediaType.MULTIPART_FORM_DATA)) +// .andDo(print()) +// .andExpect(status().isOk()) +// .andExpect(jsonPath("$.message").exists()); +// } +// +// @Test +// @DisplayName("특정_채팅방의_모든_유저_정보_조회_테스트") +// void 특정_채팅방의_모든_유저_정보_조회_테스트() throws Exception { +// // given +// ReadChatRoomMemberResponse response = ReadChatRoomMemberResponse.of(List.of(new UserInfoInSpace[]{})); +// given(chatRoomService.readChatRoomMembers(userId, spaceId)) +// .willReturn(response); +// +// // when & then +// mockMvc.perform(get("/space/{spaceId}/chat/{chatRoomId}/member", spaceId, chatRoomId)) +// .andDo(print()) +// .andExpect(status().isOk()) +// .andExpect(jsonPath("$.message").exists()); +// } +// +// @Test +// @DisplayName("특정_채팅방에_유저_초대_테스트") +// void 특정_채팅방에_유저_초대_테스트() throws Exception { +// // given +// JoinChatRoomRequest request = JoinChatRoomRequest.builder().memberList(List.of(1L)).build(); +// String content = objectMapper.writeValueAsString(request); +// +// given(chatRoomService.joinChatRoom(chatRoomId, request)) +// .willReturn(commonResponse); +// +// // when & then +// mockMvc.perform(post("/space/{spaceId}/chat/{chatRoomId}/member", spaceId, chatRoomId) +// .param("userSpaceAuth", "manager") +// .contentType(MediaType.APPLICATION_JSON) +// .content(content)) +// .andDo(print()) +// .andExpect(status().isOk()) +// .andExpect(jsonPath("$.message").exists()); +// } +// +// @Test +// @DisplayName("특정_유저가_채팅방에서_떠난_시간_저장_테스트") +// void 특정_유저가_채팅방에서_떠난_시간_저장_테스트() throws Exception { +// // given +// given(chatRoomService.updateLastReadTime(userId, chatRoomId)) +// .willReturn(commonResponse); +// +// // when & then +// mockMvc.perform(post("/space/{spaceId}/chat/{chatRoomId}/leave", spaceId, chatRoomId)) +// .andDo(print()) +// .andExpect(status().isOk()) +// .andExpect(jsonPath("$.message").exists()); +// } +// +// @Test +// @DisplayName("특정_채팅방의_이름_수정_테스트") +// void 특정_채팅방의_이름_수정_테스트() throws Exception { +// // given +// given(chatRoomService.modifyChatRoomName(chatRoomId, "newChatRoom")) +// .willReturn(commonResponse); +// +// // when & then +// mockMvc.perform(post("/space/{spaceId}/chat/{chatRoomId}/setting", spaceId, chatRoomId) +// .param("name", "newChatRoom") +// .param("userSpaceAuth", "manager")) +// .andDo(print()) +// .andExpect(status().isOk()) +// .andExpect(jsonPath("$.message").exists()); +// } +// +// @Test +// @DisplayName("특정_채팅방에서_나가기_테스트") +// void 특정_채팅방에서_나가기_테스트() throws Exception { +// // given +// given(chatRoomService.exitChatRoom(userId, chatRoomId)) +// .willReturn(commonResponse); +// +// // when & then +// mockMvc.perform(post("/space/{spaceId}/chat/{chatRoomId}/exit", spaceId, chatRoomId)) +// .andDo(print()) +// .andExpect(status().isOk()) +// .andExpect(jsonPath("$.message").exists()); +// } +// +// @Test +// @DisplayName("특정_채팅방_삭제_테스트") +// void 특정_채팅방_삭제_테스트() throws Exception { +// // given +// given(chatRoomService.deleteChatRoom(chatRoomId)) +// .willReturn(commonResponse); +// +// // when & then +// mockMvc.perform(post("/space/{spaceId}/chat/{chatRoomId}/delete", spaceId, chatRoomId) +// .param("userSpaceAuth", "manager")) +// .andDo(print()) +// .andExpect(status().isOk()) +// .andExpect(jsonPath("$.message").exists()); +// } +//} diff --git a/src/test/java/space/space_spring/repository/ChatRoomRepositoryTest.java b/src/test/java/space/space_spring/domain/chat/chatroom/repository/ChatRoomRepositoryTest.java similarity index 90% rename from src/test/java/space/space_spring/repository/ChatRoomRepositoryTest.java rename to src/test/java/space/space_spring/domain/chat/chatroom/repository/ChatRoomRepositoryTest.java index 1903647a..0c7cfce7 100644 --- a/src/test/java/space/space_spring/repository/ChatRoomRepositoryTest.java +++ b/src/test/java/space/space_spring/domain/chat/chatroom/repository/ChatRoomRepositoryTest.java @@ -5,12 +5,12 @@ //import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; //import org.springframework.context.annotation.Import; //import space.space_spring.config.QueryDslConfig; -//import space.space_spring.dao.chat.ChatRoomRepository; -//import space.space_spring.dao.chat.UserChatRoomRepository; -//import space.space_spring.entity.ChatRoom; -//import space.space_spring.domain.space.model.entity.Space; -//import space.space_spring.domain.user.model.entity.User; -//import space.space_spring.entity.UserChatRoom; +//import space.space_spring.domain.chat.chatroom.repository.ChatRoomRepository; +//import space.space_spring.domain.chat.chatroom.repository.UserChatRoomRepository; +//import space.space_spring.domain.chat.chatroom.model.ChatRoom; +//import space.space_spring.entity.Space; +//import space.space_spring.entity.User; +//import space.space_spring.domain.chat.chatroom.model.UserChatRoom; //import space.space_spring.entity.enumStatus.BaseStatusType; //import space.space_spring.entity.enumStatus.UserSignupType; // diff --git a/src/test/java/space/space_spring/repository/UserChatRoomDaoTest.java b/src/test/java/space/space_spring/domain/chat/chatroom/repository/UserChatRoomRepositoryTest.java similarity index 94% rename from src/test/java/space/space_spring/repository/UserChatRoomDaoTest.java rename to src/test/java/space/space_spring/domain/chat/chatroom/repository/UserChatRoomRepositoryTest.java index 81f0472a..7762cbd9 100644 --- a/src/test/java/space/space_spring/repository/UserChatRoomDaoTest.java +++ b/src/test/java/space/space_spring/domain/chat/chatroom/repository/UserChatRoomRepositoryTest.java @@ -7,10 +7,10 @@ //import space.space_spring.config.QueryDslConfig; //import space.space_spring.dao.chat.ChatRoomDao; //import space.space_spring.dao.chat.UserChatRoomDao; -//import space.space_spring.entity.ChatRoom; -//import space.space_spring.domain.space.model.entity.Space; -//import space.space_spring.domain.user.model.entity.User; -//import space.space_spring.entity.UserChatRoom; +//import space.space_spring.domain.chat.chatroom.model.ChatRoom; +//import space.space_spring.entity.Space; +//import space.space_spring.entity.User; +//import space.space_spring.domain.chat.chatting.model.UserChatRoom; //import space.space_spring.entity.enumStatus.UserSignupType; // //import java.time.LocalDateTime; diff --git a/src/test/java/space/space_spring/service/ChatRoomServiceTest.java b/src/test/java/space/space_spring/domain/chat/chatroom/service/ChatRoomServiceTest.java similarity index 96% rename from src/test/java/space/space_spring/service/ChatRoomServiceTest.java rename to src/test/java/space/space_spring/domain/chat/chatroom/service/ChatRoomServiceTest.java index 0f2fda26..71ade11e 100644 --- a/src/test/java/space/space_spring/service/ChatRoomServiceTest.java +++ b/src/test/java/space/space_spring/domain/chat/chatroom/service/ChatRoomServiceTest.java @@ -11,12 +11,12 @@ //import space.space_spring.dao.chat.ChatRoomDao; //import space.space_spring.dao.chat.ChattingDao; //import space.space_spring.dao.chat.UserChatRoomDao; -//import space.space_spring.dto.chat.request.CreateChatRoomRequest; -//import space.space_spring.dto.chat.request.JoinChatRoomRequest; -//import space.space_spring.dto.chat.response.ChatSuccessResponse; -//import space.space_spring.dto.chat.response.CreateChatRoomResponse; -//import space.space_spring.dto.chat.response.ReadChatRoomMemberResponse; -//import space.space_spring.dto.chat.response.ReadChatRoomResponse; +//import space.space_spring.domain.chat.chatroom.model.request.CreateChatRoomRequest; +//import space.space_spring.domain.chat.chatroom.model.request.JoinChatRoomRequest; +//import space.space_spring.domain.chat.chatroom.model.response.ChatSuccessResponse; +//import space.space_spring.domain.chat.chatroom.model.response.CreateChatRoomResponse; +//import space.space_spring.domain.chat.chatroom.model.response.ReadChatRoomMemberResponse; +//import space.space_spring.domain.chat.chatroom.model.response.ReadChatRoomResponse; //import space.space_spring.entity.*; //import space.space_spring.entity.enumStatus.UserSignupType; //import space.space_spring.entity.enumStatus.UserSpaceAuth;