Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

채팅 데이터 생성 및 모임마다의 전체 조회 기능 구현 #165

Merged
merged 9 commits into from
Aug 1, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package mouda.backend.chat.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import mouda.backend.chat.dto.request.ChatCreateRequest;
import mouda.backend.chat.dto.response.ChatFindUnloadedResponse;
import mouda.backend.chat.service.ChatService;
import mouda.backend.common.RestResponse;
import mouda.backend.member.domain.Member;

@RestController
@RequestMapping("/v1/chat")
@RequiredArgsConstructor
public class ChatController {

private final ChatService chatService;

@PostMapping
public ResponseEntity<Void> createChat(
@Valid @RequestBody ChatCreateRequest chatCreateRequest,
Member member
) {
chatService.createChat(chatCreateRequest, member);
return ResponseEntity.ok().build();
}

@GetMapping
public ResponseEntity<RestResponse<ChatFindUnloadedResponse>> findUnloadedChats(
@RequestParam Long recentChatId,
@RequestParam Long moimId,
Member member
) {
ChatFindUnloadedResponse unloadedChats = chatService.findUnloadedChats(recentChatId, moimId, member);
return ResponseEntity.ok(new RestResponse<>(unloadedChats));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package mouda.backend.chat.dto.request;

import java.time.LocalDate;
import java.time.LocalTime;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import mouda.backend.chat.domain.Chat;
import mouda.backend.member.domain.Member;
import mouda.backend.moim.domain.Moim;

public record ChatCreateRequest(
@NotNull Long moimId,
@NotBlank String content
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

통일성을 위해 어노테이션과 개행을 하는 건 어떤가요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

녜에

) {
public Chat toEntity(Moim moim, Member member) {
return Chat.builder()
.content(content)
.date(LocalDate.now())
.time(LocalTime.now())
.member(member)
.moim(moim)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package mouda.backend.chat.dto.response;

import java.time.LocalDate;
import java.time.LocalTime;

import lombok.Builder;
import mouda.backend.chat.domain.Chat;

@Builder
public record ChatFindDetailResponse(
long chatId,
String content,
long memberId,
String nickname,
LocalDate date,
LocalTime time
) {
public static ChatFindDetailResponse toResponse(Chat chat) {
return ChatFindDetailResponse.builder()
.chatId(chat.getId())
.content(chat.getContent())
.memberId(chat.getMember().getId())
.nickname(chat.getMember().getNickname())
.date(chat.getDate())
.time(chat.getTime())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package mouda.backend.chat.dto.response;

import java.util.List;

public record ChatFindUnloadedResponse(
long loginMemberId,
List<ChatFindDetailResponse> chats
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package mouda.backend.chat.exception;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum ChatErrorMessage {
MOIM_NOT_FOUND("존재하지 않는 모임에 채팅할 수 없습니다.");

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

한 줄 띄어주세요!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

녜에

private final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package mouda.backend.chat.exception;

import org.springframework.http.HttpStatus;

import mouda.backend.exception.MoudaException;

public class ChatException extends MoudaException {

public ChatException(HttpStatus httpStatus, ChatErrorMessage chatErrorMessage) {
super(httpStatus, chatErrorMessage.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package mouda.backend.chat.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import mouda.backend.chat.domain.Chat;

public interface ChatRepository extends JpaRepository<Chat, Long> {

@Query("SELECT c FROM Chat c WHERE c.moim.id = :moimId AND c.id > :chatId")
List<Chat> findAllUnloadedChats(@Param("moimId") long moimId, @Param("chatId") long chatId);
}
40 changes: 40 additions & 0 deletions backend/src/main/java/mouda/backend/chat/service/ChatService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package mouda.backend.chat.service;

import java.util.List;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import lombok.RequiredArgsConstructor;
import mouda.backend.chat.domain.Chat;
import mouda.backend.chat.dto.request.ChatCreateRequest;
import mouda.backend.chat.dto.response.ChatFindDetailResponse;
import mouda.backend.chat.dto.response.ChatFindUnloadedResponse;
import mouda.backend.chat.exception.ChatErrorMessage;
import mouda.backend.chat.exception.ChatException;
import mouda.backend.chat.repository.ChatRepository;
import mouda.backend.member.domain.Member;
import mouda.backend.moim.domain.Moim;
import mouda.backend.moim.repository.MoimRepository;

@Service
@RequiredArgsConstructor
public class ChatService {

private final ChatRepository chatRepository;
private final MoimRepository moimRepository;

public void createChat(ChatCreateRequest chatCreateRequest, Member member) {
Moim moim = moimRepository.findById(chatCreateRequest.moimId())
.orElseThrow(() -> new ChatException(HttpStatus.BAD_REQUEST, ChatErrorMessage.MOIM_NOT_FOUND));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 모임이 없는 경우 (moim패키지가 아니더라도) MoimException을 발생시켰는데 , 이 부분에 대해 이야기하고 통일하면 좋을 것 같아요~

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

녜에

Chat chat = chatCreateRequest.toEntity(moim, member);
chatRepository.save(chat);
}

public ChatFindUnloadedResponse findUnloadedChats(long recentChatId, long moimId, Member member) {
List<ChatFindDetailResponse> chats = chatRepository.findAllUnloadedChats(moimId, recentChatId).stream()
.map(ChatFindDetailResponse::toResponse)
.toList();
return new ChatFindUnloadedResponse(member.getId(), chats);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 띄어쓰기를 의미 단위로 자르는 걸 좋아하는데 리턴문과 채팅을 가져오는 단계를 구분하는 것은 어떤가요???

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

녜에

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package mouda.backend.chat.repository;

import static org.assertj.core.api.Assertions.*;

import java.util.List;

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.orm.jpa.DataJpaTest;

import mouda.backend.chat.domain.Chat;
import mouda.backend.fixture.ChatFixture;
import mouda.backend.fixture.MemberFixture;
import mouda.backend.fixture.MoimFixture;
import mouda.backend.member.domain.Member;
import mouda.backend.member.repository.MemberRepository;
import mouda.backend.moim.domain.Moim;
import mouda.backend.moim.repository.MoimRepository;

@DataJpaTest
class ChatRepositoryTest {

@Autowired
private ChatRepository chatRepository;

@Autowired
private MoimRepository moimRepository;

@Autowired
private MemberRepository memberRepository;

@DisplayName("모임 아이디가 동일하고 채팅 아이디가 더 큰 채팅 리스트가 조회된다.")
@Test
void test() {
Moim moim = MoimFixture.getCoffeeMoim();
moimRepository.save(moim);

Member member1 = MemberFixture.getAnna();
Member member2 = MemberFixture.getHogee();

memberRepository.save(member1);
memberRepository.save(member2);

Chat anna = ChatFixture.getChatWithMemberAtMoim(member1, moim);
chatRepository.save(anna);
Chat hogee = ChatFixture.getChatWithMemberAtMoim(member2, moim);
chatRepository.save(hogee);

List<Chat> chats = chatRepository.findAllUnloadedChats(1L, 1L);

assertThat(chats).hasSize(1);
}
}
30 changes: 6 additions & 24 deletions backend/src/test/java/mouda/backend/fixture/ChatFixture.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,18 @@
import java.time.LocalTime;

import mouda.backend.chat.domain.Chat;
import mouda.backend.member.domain.Member;
import mouda.backend.moim.domain.Moim;

public class ChatFixture {

public static Chat getChatWithHogeeAtBasketballMoim() {
public static Chat getChatWithMemberAtMoim(Member member, Moim moim) {
return Chat.builder()
.time(LocalTime.now())
.date(LocalDate.now())
.content("ㅎㅇㅎㅇ")
.member(MemberFixture.getHogee())
.moim(MoimFixture.getBasketballMoim())
.build();
}

public static Chat getChatWithAnnaAtCoffeeMoim() {
return Chat.builder()
.time(LocalTime.now())
.date(LocalDate.now())
.content("반갑읍니다")
.member(MemberFixture.getAnna())
.moim(MoimFixture.getCoffeeMoim())
.build();
}

public static Chat getChatWithTebahAtSoccerMoim() {
return Chat.builder()
.time(LocalTime.now())
.date(LocalDate.now())
.content("ㅎㅇㅎㅇ")
.member(MemberFixture.getTebah())
.moim(MoimFixture.getSoccerMoim())
.content("안녕하쎄요")
.member(member)
.moim(moim)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public static Moim getCoffeeMoim() {
.date(LocalDate.now().plusDays(1))
.place("안나 집")
.description("커피 머신 들고와라")
.maxPeople(100)
.maxPeople(60)
.build();
}
}