diff --git a/src/main/java/com/dnd/gongmuin/answer/controller/AnswerController.java b/src/main/java/com/dnd/gongmuin/answer/controller/AnswerController.java index ddd2913f..799b5986 100644 --- a/src/main/java/com/dnd/gongmuin/answer/controller/AnswerController.java +++ b/src/main/java/com/dnd/gongmuin/answer/controller/AnswerController.java @@ -52,7 +52,7 @@ public ResponseEntity> getAnswersByQuestionPo @ApiResponse(useReturnTypeSchema = true) @PostMapping("/api/question-posts/answers/{answerId}") public ResponseEntity getAnswersByQuestionPostId( - @PathVariable Long answerId, + @PathVariable("answerId") Long answerId, @AuthenticationPrincipal Member member ) { AnswerDetailResponse response = answerService.chooseAnswer(answerId, member); diff --git a/src/main/java/com/dnd/gongmuin/answer/dto/AnswerDetailResponse.java b/src/main/java/com/dnd/gongmuin/answer/dto/AnswerDetailResponse.java index fa09a159..dc74d5da 100644 --- a/src/main/java/com/dnd/gongmuin/answer/dto/AnswerDetailResponse.java +++ b/src/main/java/com/dnd/gongmuin/answer/dto/AnswerDetailResponse.java @@ -1,6 +1,6 @@ package com.dnd.gongmuin.answer.dto; -import com.dnd.gongmuin.question_post.dto.response.MemberInfo; +import com.dnd.gongmuin.member.dto.response.MemberInfo; public record AnswerDetailResponse( Long answerId, diff --git a/src/main/java/com/dnd/gongmuin/answer/dto/AnswerMapper.java b/src/main/java/com/dnd/gongmuin/answer/dto/AnswerMapper.java index b6187fb1..5738fae7 100644 --- a/src/main/java/com/dnd/gongmuin/answer/dto/AnswerMapper.java +++ b/src/main/java/com/dnd/gongmuin/answer/dto/AnswerMapper.java @@ -2,7 +2,7 @@ import com.dnd.gongmuin.answer.domain.Answer; import com.dnd.gongmuin.member.domain.Member; -import com.dnd.gongmuin.question_post.dto.response.MemberInfo; +import com.dnd.gongmuin.member.dto.response.MemberInfo; import lombok.AccessLevel; import lombok.NoArgsConstructor; diff --git a/src/main/java/com/dnd/gongmuin/answer/repository/AnswerRepository.java b/src/main/java/com/dnd/gongmuin/answer/repository/AnswerRepository.java index e170f249..7577930c 100644 --- a/src/main/java/com/dnd/gongmuin/answer/repository/AnswerRepository.java +++ b/src/main/java/com/dnd/gongmuin/answer/repository/AnswerRepository.java @@ -1,6 +1,7 @@ package com.dnd.gongmuin.answer.repository; import java.util.List; +import java.util.Optional; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; @@ -21,4 +22,8 @@ public interface AnswerRepository extends JpaRepository { @Modifying(flushAutomatically = true, clearAutomatically = true) @Query("UPDATE Answer a SET a.member = :member WHERE a.member.id = :memberId") void updateAnswersMember(Long memberId, Member member); + + @Query("select a from Answer a " + + "join fetch a.member where a.id = :answerId") + Optional findByIdWithMember(Long answerId); } \ No newline at end of file diff --git a/src/main/java/com/dnd/gongmuin/answer/repository/AnswerSimpleQueryRepository.java b/src/main/java/com/dnd/gongmuin/answer/repository/AnswerSimpleQueryRepository.java new file mode 100644 index 00000000..53bc7419 --- /dev/null +++ b/src/main/java/com/dnd/gongmuin/answer/repository/AnswerSimpleQueryRepository.java @@ -0,0 +1,28 @@ +package com.dnd.gongmuin.answer.repository; + +import java.util.Optional; + +import org.springframework.stereotype.Repository; + +import com.dnd.gongmuin.answer.domain.Answer; + +import jakarta.persistence.EntityManager; +import lombok.RequiredArgsConstructor; + +@Repository +@RequiredArgsConstructor +public class AnswerSimpleQueryRepository { + + private final EntityManager em; + + public Optional findAnswerById(Long answerId) { + Answer answer = em.createQuery( + "select a from Answer a" + + " join fetch a.member m" + + " where a.id = :answerId", Answer.class + ) + .setParameter("answerId", answerId) + .getSingleResult(); + return Optional.of(answer); + } +} diff --git a/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java b/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java index 81b7ef7e..027c93c9 100644 --- a/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java +++ b/src/main/java/com/dnd/gongmuin/answer/service/AnswerService.java @@ -47,7 +47,7 @@ public AnswerDetailResponse registerAnswer( RegisterAnswerRequest request, Member member ) { - QuestionPost questionPost = findQuestionPostById(questionPostId); + QuestionPost questionPost = getQuestionPostById(questionPostId); Answer answer = AnswerMapper.toAnswer(questionPostId, questionPost.isQuestioner(member.getId()), request, member); Answer savedAnswer = answerRepository.save(answer); @@ -73,8 +73,8 @@ public AnswerDetailResponse chooseAnswer( Long answerId, Member member ) { - Answer answer = getAnswerById(answerId); - QuestionPost questionPost = findQuestionPostById(answer.getQuestionPostId()); + Answer answer = getAnswerWithMember(answerId); + QuestionPost questionPost = getQuestionPostWithMember(answer.getQuestionPostId()); validateIfQuestioner(member, questionPost); chooseAnswer(questionPost, answer); @@ -99,13 +99,18 @@ private void validateIfQuestionPostExists(Long questionPostId) { } } - private Answer getAnswerById(Long answerId) { - return answerRepository.findById(answerId) + private Answer getAnswerWithMember(Long answerId) { + return answerRepository.findByIdWithMember(answerId) .orElseThrow(() -> new NotFoundException(AnswerErrorCode.NOT_FOUND_ANSWER)); } - private QuestionPost findQuestionPostById(Long questionPostId) { + private QuestionPost getQuestionPostById(Long questionPostId) { return questionPostRepository.findById(questionPostId) .orElseThrow(() -> new NotFoundException(QuestionPostErrorCode.NOT_FOUND_QUESTION_POST)); } + + private QuestionPost getQuestionPostWithMember(Long questionPostId) { + return questionPostRepository.findByIdWithMember(questionPostId) + .orElseThrow(() -> new NotFoundException(QuestionPostErrorCode.NOT_FOUND_QUESTION_POST)); + } } \ No newline at end of file diff --git a/src/main/java/com/dnd/gongmuin/auth/service/AuthService.java b/src/main/java/com/dnd/gongmuin/auth/service/AuthService.java index 43106ca5..d0236181 100644 --- a/src/main/java/com/dnd/gongmuin/auth/service/AuthService.java +++ b/src/main/java/com/dnd/gongmuin/auth/service/AuthService.java @@ -74,13 +74,13 @@ public TempSignResponse tempSignUp(TempSignUpRequest tempSignUpRequest, HttpServ throw new NotFoundException(MemberErrorCode.NOT_FOUND_MEMBER); } - memberRepository.save(member); + Member savedMember = memberRepository.save(member); AuthInfo authInfo = AuthInfo.of(member.getSocialName(), member.getSocialEmail(), member.getRole()); CustomOauth2User customOauth2User = new CustomOauth2User(authInfo); - tokenProvider.generateRefreshToken(customOauth2User, now); - String accessToken = tokenProvider.generateAccessToken(customOauth2User, now); + tokenProvider.generateRefreshToken(savedMember, customOauth2User, now); + String accessToken = tokenProvider.generateAccessToken(savedMember, customOauth2User, now); response.addCookie(cookieUtil.createCookie(accessToken)); return new TempSignResponse(true); @@ -98,8 +98,8 @@ public TempSignResponse tempSignIn(TempSignInRequest tempSignInRequest, HttpServ AuthInfo authInfo = AuthInfo.of(member.getSocialName(), member.getSocialEmail(), member.getRole()); CustomOauth2User customOauth2User = new CustomOauth2User(authInfo); - tokenProvider.generateRefreshToken(customOauth2User, now); - String accessToken = tokenProvider.generateAccessToken(customOauth2User, now); + tokenProvider.generateRefreshToken(member, customOauth2User, now); + String accessToken = tokenProvider.generateAccessToken(member, customOauth2User, now); response.addCookie(cookieUtil.createCookie(accessToken)); return new TempSignResponse(true); @@ -175,8 +175,8 @@ public ReissueResponse reissue(HttpServletRequest request, HttpServletResponse r CustomOauth2User customUser = new CustomOauth2User( AuthInfo.of(member.getSocialName(), member.getSocialEmail(), member.getRole())); - String reissuedAccessToken = tokenProvider.generateAccessToken(customUser, new Date()); - tokenProvider.generateRefreshToken(customUser, new Date()); + String reissuedAccessToken = tokenProvider.generateAccessToken(member, customUser, new Date()); + tokenProvider.generateRefreshToken(member, customUser, new Date()); response.addCookie(cookieUtil.createCookie(reissuedAccessToken)); diff --git a/src/main/java/com/dnd/gongmuin/chat_inquiry/controller/ChatInquiryController.java b/src/main/java/com/dnd/gongmuin/chat_inquiry/controller/ChatInquiryController.java index 4ee2e0e4..c9818a41 100644 --- a/src/main/java/com/dnd/gongmuin/chat_inquiry/controller/ChatInquiryController.java +++ b/src/main/java/com/dnd/gongmuin/chat_inquiry/controller/ChatInquiryController.java @@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.RestController; import com.dnd.gongmuin.chat_inquiry.dto.AcceptChatResponse; +import com.dnd.gongmuin.chat_inquiry.dto.ChatInquiryDetailResponse; import com.dnd.gongmuin.chat_inquiry.dto.ChatInquiryResponse; import com.dnd.gongmuin.chat_inquiry.dto.CreateChatInquiryRequest; import com.dnd.gongmuin.chat_inquiry.dto.CreateChatInquiryResponse; @@ -42,7 +43,17 @@ public ResponseEntity createChatInquiry( return ResponseEntity.ok(response); } - @Operation(summary = "채팅방 요청 목록 조회 API", description = "회원의 채팅방 목록을 조회한다.") + @Operation(summary = "채팅 요청 상세 조회 API", description = "채팅방 요청을 조회한다.") + @GetMapping("/api/chat/inquiries/{chatInquiryId}") + public ResponseEntity getChatInquiryById( + @PathVariable("chatInquiryId") Long chatInquiryId, + @AuthenticationPrincipal Member member + ) { + ChatInquiryDetailResponse response = chatInquiryService.getChatInquiryById(chatInquiryId, member); + return ResponseEntity.ok(response); + } + + @Operation(summary = "채팅 요청 목록 조회 API", description = "회원의 채팅 목록을 조회한다.") @GetMapping("/api/chat/inquiries") public ResponseEntity> getChatInquiresByMember( @AuthenticationPrincipal Member member, diff --git a/src/main/java/com/dnd/gongmuin/chat_inquiry/domain/ChatInquiry.java b/src/main/java/com/dnd/gongmuin/chat_inquiry/domain/ChatInquiry.java index 378b4bf6..2b905042 100644 --- a/src/main/java/com/dnd/gongmuin/chat_inquiry/domain/ChatInquiry.java +++ b/src/main/java/com/dnd/gongmuin/chat_inquiry/domain/ChatInquiry.java @@ -31,7 +31,7 @@ public class ChatInquiry extends TimeBaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "chat_proposal_id", nullable = false) + @Column(name = "chat_inquiry_id", nullable = false) private Long id; @ManyToOne(fetch = LAZY) @@ -90,4 +90,12 @@ public void updateStatusRejected() { status = InquiryStatus.REJECTED; inquirer.increaseCredit(CHAT_REWARD); } + + public boolean isInquirer(Member member) { + return member.equals(this.inquirer); + } + + public Member getChatPartner(Member member) { + return isInquirer(member) ? this.answerer : this.inquirer; + } } diff --git a/src/main/java/com/dnd/gongmuin/chat_inquiry/dto/ChatInquiryDetailResponse.java b/src/main/java/com/dnd/gongmuin/chat_inquiry/dto/ChatInquiryDetailResponse.java new file mode 100644 index 00000000..08aba1a3 --- /dev/null +++ b/src/main/java/com/dnd/gongmuin/chat_inquiry/dto/ChatInquiryDetailResponse.java @@ -0,0 +1,12 @@ +package com.dnd.gongmuin.chat_inquiry.dto; + +import com.dnd.gongmuin.member.dto.response.MemberInfo; + +public record ChatInquiryDetailResponse( + Long chatInquiryId, + String inquiryMessage, + String inquiryStatus, + boolean isInquirer, + MemberInfo chatPartner +) { +} diff --git a/src/main/java/com/dnd/gongmuin/chat_inquiry/dto/ChatInquiryMapper.java b/src/main/java/com/dnd/gongmuin/chat_inquiry/dto/ChatInquiryMapper.java index 4a3486ec..6e55d9de 100644 --- a/src/main/java/com/dnd/gongmuin/chat_inquiry/dto/ChatInquiryMapper.java +++ b/src/main/java/com/dnd/gongmuin/chat_inquiry/dto/ChatInquiryMapper.java @@ -4,8 +4,8 @@ import com.dnd.gongmuin.chat_inquiry.domain.InquiryStatus; import com.dnd.gongmuin.chatroom.domain.ChatRoom; import com.dnd.gongmuin.member.domain.Member; +import com.dnd.gongmuin.member.dto.response.MemberInfo; import com.dnd.gongmuin.question_post.domain.QuestionPost; -import com.dnd.gongmuin.question_post.dto.response.MemberInfo; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -44,6 +44,24 @@ public static CreateChatInquiryResponse toCreateChatInquiryResponse( ); } + public static ChatInquiryDetailResponse toChatInquiryDetailResponse( + ChatInquiry chatInquiry, + Member chatPartner, + boolean isInquirer + ) { + return new ChatInquiryDetailResponse(chatInquiry.getId(), + chatInquiry.getMessage(), + chatInquiry.getStatus().getLabel(), + isInquirer, + new MemberInfo( + chatPartner.getId(), + chatPartner.getNickname(), + chatPartner.getJobGroup().getLabel(), + chatPartner.getProfileImageNo() + ) + ); + } + public static AcceptChatResponse toAcceptChatResponse( ChatInquiry chatInquiry, ChatRoom chatRoom diff --git a/src/main/java/com/dnd/gongmuin/chat_inquiry/dto/ChatInquiryResponse.java b/src/main/java/com/dnd/gongmuin/chat_inquiry/dto/ChatInquiryResponse.java index 87bdb0e9..468315c3 100644 --- a/src/main/java/com/dnd/gongmuin/chat_inquiry/dto/ChatInquiryResponse.java +++ b/src/main/java/com/dnd/gongmuin/chat_inquiry/dto/ChatInquiryResponse.java @@ -1,8 +1,8 @@ package com.dnd.gongmuin.chat_inquiry.dto; -import com.dnd.gongmuin.chat_inquiry.domain.InquiryStatus; -import com.dnd.gongmuin.member.domain.JobGroup; -import com.dnd.gongmuin.question_post.dto.response.MemberInfo; +import com.dnd.gongmuin.chat_inquiry.domain.ChatInquiry; +import com.dnd.gongmuin.member.domain.Member; +import com.dnd.gongmuin.member.dto.response.MemberInfo; import com.querydsl.core.annotations.QueryProjection; public record ChatInquiryResponse( @@ -10,30 +10,31 @@ public record ChatInquiryResponse( String inquiryMessage, String inquiryStatus, boolean isInquirer, - MemberInfo chatPartner + MemberInfo chatPartner, + String createdAt ) { @QueryProjection public ChatInquiryResponse( - Long chatInquiryId, - String inquiryMessage, - InquiryStatus inquiryStatus, - boolean isInquirer, - Long partnerId, - String partnerNickname, - JobGroup partnerJobGroup, - int partnerProfileImageNo + ChatInquiry chatInquiry, + boolean isInquirer ) { this( - chatInquiryId, - inquiryMessage, - inquiryStatus.getLabel(), + chatInquiry.getId(), + chatInquiry.getMessage(), + chatInquiry.getStatus().getLabel(), isInquirer, - new MemberInfo( - partnerId, - partnerNickname, - partnerJobGroup.getLabel(), - partnerProfileImageNo - ) + createPartnerInfo(isInquirer, chatInquiry), + chatInquiry.getCreatedAt().toString() + ); + } + + private static MemberInfo createPartnerInfo(boolean isInquirer, ChatInquiry chatInquiry) { + Member partner = isInquirer ? chatInquiry.getAnswerer() : chatInquiry.getInquirer(); + return new MemberInfo( + partner.getId(), + partner.getNickname(), + partner.getJobGroup().getLabel(), + partner.getProfileImageNo() ); } } diff --git a/src/main/java/com/dnd/gongmuin/chat_inquiry/dto/CreateChatInquiryResponse.java b/src/main/java/com/dnd/gongmuin/chat_inquiry/dto/CreateChatInquiryResponse.java index 24080f16..cb77519d 100644 --- a/src/main/java/com/dnd/gongmuin/chat_inquiry/dto/CreateChatInquiryResponse.java +++ b/src/main/java/com/dnd/gongmuin/chat_inquiry/dto/CreateChatInquiryResponse.java @@ -1,6 +1,6 @@ package com.dnd.gongmuin.chat_inquiry.dto; -import com.dnd.gongmuin.question_post.dto.response.MemberInfo; +import com.dnd.gongmuin.member.dto.response.MemberInfo; public record CreateChatInquiryResponse( Long chatInquiryId, diff --git a/src/main/java/com/dnd/gongmuin/chat_inquiry/repository/ChatInquiryQueryRepositoryImpl.java b/src/main/java/com/dnd/gongmuin/chat_inquiry/repository/ChatInquiryQueryRepositoryImpl.java index 0510d2df..b8fa741a 100644 --- a/src/main/java/com/dnd/gongmuin/chat_inquiry/repository/ChatInquiryQueryRepositoryImpl.java +++ b/src/main/java/com/dnd/gongmuin/chat_inquiry/repository/ChatInquiryQueryRepositoryImpl.java @@ -26,29 +26,11 @@ public class ChatInquiryQueryRepositoryImpl implements ChatInquiryQueryRepositor public Slice getChatInquiresByMember(Member member, Pageable pageable) { List content = queryFactory .select(new QChatInquiryResponse( - chatInquiry.id, - chatInquiry.message, - chatInquiry.status, + chatInquiry, new CaseBuilder() .when(chatInquiry.inquirer.id.eq(member.getId())) .then(true) - .otherwise(false), - new CaseBuilder() - .when(chatInquiry.inquirer.id.eq(member.getId())) - .then(chatInquiry.answerer.id) - .otherwise(chatInquiry.inquirer.id), - new CaseBuilder() - .when(chatInquiry.inquirer.id.eq(member.getId())) - .then(chatInquiry.answerer.nickname) - .otherwise(chatInquiry.inquirer.nickname), - new CaseBuilder() - .when(chatInquiry.inquirer.id.eq(member.getId())) - .then(chatInquiry.answerer.jobGroup) - .otherwise(chatInquiry.inquirer.jobGroup), - new CaseBuilder() - .when(chatInquiry.inquirer.id.eq(member.getId())) - .then(chatInquiry.answerer.profileImageNo) - .otherwise(chatInquiry.inquirer.profileImageNo) + .otherwise(false) )) .from(chatInquiry) .where(chatInquiry.inquirer.id.eq(member.getId()) diff --git a/src/main/java/com/dnd/gongmuin/chat_inquiry/service/ChatInquiryService.java b/src/main/java/com/dnd/gongmuin/chat_inquiry/service/ChatInquiryService.java index db7e13c8..44f2db35 100644 --- a/src/main/java/com/dnd/gongmuin/chat_inquiry/service/ChatInquiryService.java +++ b/src/main/java/com/dnd/gongmuin/chat_inquiry/service/ChatInquiryService.java @@ -11,6 +11,7 @@ import com.dnd.gongmuin.chat_inquiry.domain.ChatInquiry; import com.dnd.gongmuin.chat_inquiry.dto.AcceptChatResponse; +import com.dnd.gongmuin.chat_inquiry.dto.ChatInquiryDetailResponse; import com.dnd.gongmuin.chat_inquiry.dto.ChatInquiryMapper; import com.dnd.gongmuin.chat_inquiry.dto.ChatInquiryResponse; import com.dnd.gongmuin.chat_inquiry.dto.CreateChatInquiryRequest; @@ -70,6 +71,17 @@ public CreateChatInquiryResponse createChatInquiry(CreateChatInquiryRequest requ return ChatInquiryMapper.toCreateChatInquiryResponse(chatInquiry); } + @Transactional(readOnly = true) + public ChatInquiryDetailResponse getChatInquiryById(Long chatInquiryId, Member member) { + ChatInquiry chatInquiry = getChatInquiryById(chatInquiryId); + + return ChatInquiryMapper.toChatInquiryDetailResponse( + chatInquiry, + chatInquiry.getChatPartner(member), + chatInquiry.isInquirer(member) + ); + } + @Transactional(readOnly = true) public PageResponse getChatInquiresByMember(Member member, Pageable pageable) { Slice responsePage = chatInquiryRepository.getChatInquiresByMember( diff --git a/src/main/java/com/dnd/gongmuin/chatroom/domain/ChatRoom.java b/src/main/java/com/dnd/gongmuin/chatroom/domain/ChatRoom.java index 97a6be8c..9fa16197 100644 --- a/src/main/java/com/dnd/gongmuin/chatroom/domain/ChatRoom.java +++ b/src/main/java/com/dnd/gongmuin/chatroom/domain/ChatRoom.java @@ -58,4 +58,12 @@ public static ChatRoom of( ) { return new ChatRoom(questionPost, inquirer, answerer); } + + public boolean isInquirer(Member member) { + return member.equals(this.inquirer); + } + + public Member getChatPartner(Member member) { + return isInquirer(member) ? this.answerer : this.inquirer; + } } diff --git a/src/main/java/com/dnd/gongmuin/chatroom/dto/ChatRoomMapper.java b/src/main/java/com/dnd/gongmuin/chatroom/dto/ChatRoomMapper.java index 7f7eb957..58e21e0c 100644 --- a/src/main/java/com/dnd/gongmuin/chatroom/dto/ChatRoomMapper.java +++ b/src/main/java/com/dnd/gongmuin/chatroom/dto/ChatRoomMapper.java @@ -6,8 +6,8 @@ import com.dnd.gongmuin.chatroom.dto.response.ChatRoomSimpleResponse; import com.dnd.gongmuin.chatroom.dto.response.LatestChatMessage; import com.dnd.gongmuin.member.domain.Member; +import com.dnd.gongmuin.member.dto.response.MemberInfo; import com.dnd.gongmuin.question_post.domain.QuestionPost; -import com.dnd.gongmuin.question_post.dto.response.MemberInfo; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -29,10 +29,10 @@ public static ChatRoom toChatRoom( public static ChatRoomDetailResponse toChatRoomDetailResponse( ChatRoom chatRoom, - Member chatPartner + Member chatPartner, + boolean isInquirer ) { QuestionPost questionPost = chatRoom.getQuestionPost(); - boolean isInquirer = !chatPartner.equals(chatRoom.getInquirer()); return new ChatRoomDetailResponse( questionPost.getId(), questionPost.getJobGroup().getLabel(), diff --git a/src/main/java/com/dnd/gongmuin/chatroom/dto/response/ChatRoomDetailResponse.java b/src/main/java/com/dnd/gongmuin/chatroom/dto/response/ChatRoomDetailResponse.java index 86b3fb3e..6c90366e 100644 --- a/src/main/java/com/dnd/gongmuin/chatroom/dto/response/ChatRoomDetailResponse.java +++ b/src/main/java/com/dnd/gongmuin/chatroom/dto/response/ChatRoomDetailResponse.java @@ -1,6 +1,6 @@ package com.dnd.gongmuin.chatroom.dto.response; -import com.dnd.gongmuin.question_post.dto.response.MemberInfo; +import com.dnd.gongmuin.member.dto.response.MemberInfo; public record ChatRoomDetailResponse( Long questionPostId, diff --git a/src/main/java/com/dnd/gongmuin/chatroom/dto/response/ChatRoomSimpleResponse.java b/src/main/java/com/dnd/gongmuin/chatroom/dto/response/ChatRoomSimpleResponse.java index aa7fa435..b4737ff8 100644 --- a/src/main/java/com/dnd/gongmuin/chatroom/dto/response/ChatRoomSimpleResponse.java +++ b/src/main/java/com/dnd/gongmuin/chatroom/dto/response/ChatRoomSimpleResponse.java @@ -1,6 +1,6 @@ package com.dnd.gongmuin.chatroom.dto.response; -import com.dnd.gongmuin.question_post.dto.response.MemberInfo; +import com.dnd.gongmuin.member.dto.response.MemberInfo; public record ChatRoomSimpleResponse( Long chatRoomId, diff --git a/src/main/java/com/dnd/gongmuin/chatroom/exception/ChatErrorCode.java b/src/main/java/com/dnd/gongmuin/chatroom/exception/ChatErrorCode.java index c3b182b8..24429e5a 100644 --- a/src/main/java/com/dnd/gongmuin/chatroom/exception/ChatErrorCode.java +++ b/src/main/java/com/dnd/gongmuin/chatroom/exception/ChatErrorCode.java @@ -10,8 +10,7 @@ public enum ChatErrorCode implements ErrorCode { INVALID_MESSAGE_TYPE("메시지 타입을 올바르게 입력해주세요.", "CH_001"), - NOT_FOUND_CHAT_ROOM("해당 아이디의 채팅방이 존재하지 않습니다.", "CH_002"), - UNAUTHORIZED_CHAT_ROOM("채팅방 조회 권한이 없습니다.", "CH_003"); + NOT_FOUND_CHAT_ROOM("해당 아이디의 채팅방이 존재하지 않습니다.", "CH_002"); private final String message; private final String code; diff --git a/src/main/java/com/dnd/gongmuin/chatroom/service/ChatRoomService.java b/src/main/java/com/dnd/gongmuin/chatroom/service/ChatRoomService.java index 69d9d916..d0b7b0dd 100644 --- a/src/main/java/com/dnd/gongmuin/chatroom/service/ChatRoomService.java +++ b/src/main/java/com/dnd/gongmuin/chatroom/service/ChatRoomService.java @@ -25,7 +25,6 @@ import com.dnd.gongmuin.common.dto.PageMapper; import com.dnd.gongmuin.common.dto.PageResponse; import com.dnd.gongmuin.common.exception.runtime.NotFoundException; -import com.dnd.gongmuin.common.exception.runtime.ValidationException; import com.dnd.gongmuin.member.domain.Member; import lombok.RequiredArgsConstructor; @@ -73,8 +72,12 @@ public PageResponse getChatRoomsByMember(Member member, @Transactional(readOnly = true) public ChatRoomDetailResponse getChatRoomById(Long chatRoomId, Member member) { ChatRoom chatRoom = getChatRoomById(chatRoomId); - Member chatPartner = getChatPartner(member, chatRoom); - return ChatRoomMapper.toChatRoomDetailResponse(chatRoom, chatPartner); + + return ChatRoomMapper.toChatRoomDetailResponse( + chatRoom, + chatRoom.getChatPartner(member), + chatRoom.isInquirer(member) + ); } private List getChatRoomSimpleResponses(List latestChatMessages, @@ -101,14 +104,4 @@ private ChatRoom getChatRoomById(Long id) { return chatRoomRepository.findById(id) .orElseThrow(() -> new NotFoundException(ChatErrorCode.NOT_FOUND_CHAT_ROOM)); } - - private Member getChatPartner(Member member, ChatRoom chatRoom) { - if (member.equals(chatRoom.getAnswerer())) { - return chatRoom.getInquirer(); - } - if (member.equals(chatRoom.getInquirer())) { - return chatRoom.getAnswerer(); - } - throw new ValidationException(ChatErrorCode.UNAUTHORIZED_CHAT_ROOM); - } } diff --git a/src/main/java/com/dnd/gongmuin/question_post/dto/response/MemberInfo.java b/src/main/java/com/dnd/gongmuin/member/dto/response/MemberInfo.java similarity index 67% rename from src/main/java/com/dnd/gongmuin/question_post/dto/response/MemberInfo.java rename to src/main/java/com/dnd/gongmuin/member/dto/response/MemberInfo.java index f16a0c4f..0556c88b 100644 --- a/src/main/java/com/dnd/gongmuin/question_post/dto/response/MemberInfo.java +++ b/src/main/java/com/dnd/gongmuin/member/dto/response/MemberInfo.java @@ -1,4 +1,4 @@ -package com.dnd.gongmuin.question_post.dto.response; +package com.dnd.gongmuin.member.dto.response; public record MemberInfo( Long memberId, diff --git a/src/main/java/com/dnd/gongmuin/question_post/dto/QuestionPostMapper.java b/src/main/java/com/dnd/gongmuin/question_post/dto/QuestionPostMapper.java index 6375bd9e..698eb808 100644 --- a/src/main/java/com/dnd/gongmuin/question_post/dto/QuestionPostMapper.java +++ b/src/main/java/com/dnd/gongmuin/question_post/dto/QuestionPostMapper.java @@ -6,10 +6,10 @@ import com.dnd.gongmuin.member.domain.JobGroup; import com.dnd.gongmuin.member.domain.Member; +import com.dnd.gongmuin.member.dto.response.MemberInfo; import com.dnd.gongmuin.question_post.domain.QuestionPost; import com.dnd.gongmuin.question_post.domain.QuestionPostImage; import com.dnd.gongmuin.question_post.dto.request.RegisterQuestionPostRequest; -import com.dnd.gongmuin.question_post.dto.response.MemberInfo; import com.dnd.gongmuin.question_post.dto.response.QuestionPostDetailResponse; import com.dnd.gongmuin.question_post.dto.response.RegisterQuestionPostResponse; import com.dnd.gongmuin.question_post.dto.response.UpdateQuestionPostResponse; diff --git a/src/main/java/com/dnd/gongmuin/question_post/dto/response/QuestionPostDetailResponse.java b/src/main/java/com/dnd/gongmuin/question_post/dto/response/QuestionPostDetailResponse.java index 935cb504..de942c56 100644 --- a/src/main/java/com/dnd/gongmuin/question_post/dto/response/QuestionPostDetailResponse.java +++ b/src/main/java/com/dnd/gongmuin/question_post/dto/response/QuestionPostDetailResponse.java @@ -2,6 +2,8 @@ import java.util.List; +import com.dnd.gongmuin.member.dto.response.MemberInfo; + public record QuestionPostDetailResponse( Long questionPostId, String title, diff --git a/src/main/java/com/dnd/gongmuin/question_post/dto/response/RegisterQuestionPostResponse.java b/src/main/java/com/dnd/gongmuin/question_post/dto/response/RegisterQuestionPostResponse.java index fc1633c5..649285fc 100644 --- a/src/main/java/com/dnd/gongmuin/question_post/dto/response/RegisterQuestionPostResponse.java +++ b/src/main/java/com/dnd/gongmuin/question_post/dto/response/RegisterQuestionPostResponse.java @@ -2,6 +2,8 @@ import java.util.List; +import com.dnd.gongmuin.member.dto.response.MemberInfo; + public record RegisterQuestionPostResponse( Long questionPostId, String title, diff --git a/src/main/java/com/dnd/gongmuin/question_post/repository/QuestionPostRepository.java b/src/main/java/com/dnd/gongmuin/question_post/repository/QuestionPostRepository.java index 39d750fb..5fc33635 100644 --- a/src/main/java/com/dnd/gongmuin/question_post/repository/QuestionPostRepository.java +++ b/src/main/java/com/dnd/gongmuin/question_post/repository/QuestionPostRepository.java @@ -1,6 +1,7 @@ package com.dnd.gongmuin.question_post.repository; import java.util.List; +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; @@ -16,7 +17,11 @@ public interface QuestionPostRepository extends JpaRepository findAllByMember(Member member); + @Query("select q from QuestionPost q " + + "join fetch q.member where q.id = :questionPostId") + Optional findByIdWithMember(Long questionPostId); + @Modifying(flushAutomatically = true, clearAutomatically = true) @Query("UPDATE QuestionPost q SET q.member = :member WHERE q.member.id = :memberId") - public void updateQuestionPostsMember(Long memberId, Member member); + void updateQuestionPostsMember(Long memberId, Member member); } \ No newline at end of file diff --git a/src/main/java/com/dnd/gongmuin/question_post/repository/QuestionPostSimpleQueryRepository.java b/src/main/java/com/dnd/gongmuin/question_post/repository/QuestionPostSimpleQueryRepository.java new file mode 100644 index 00000000..01120751 --- /dev/null +++ b/src/main/java/com/dnd/gongmuin/question_post/repository/QuestionPostSimpleQueryRepository.java @@ -0,0 +1,28 @@ +package com.dnd.gongmuin.question_post.repository; + +import java.util.Optional; + +import org.springframework.stereotype.Repository; + +import com.dnd.gongmuin.question_post.domain.QuestionPost; + +import jakarta.persistence.EntityManager; +import lombok.RequiredArgsConstructor; + +@Repository +@RequiredArgsConstructor +public class QuestionPostSimpleQueryRepository { + + private final EntityManager em; + + public Optional findQuestionPostById(Long questionPostId) { + QuestionPost questionPost = em.createQuery( + "select q from QuestionPost q" + + " join fetch q.member m" + + " where q.id = :questionPostId", QuestionPost.class + ) + .setParameter("questionPostId", questionPostId) + .getSingleResult(); + return Optional.of(questionPost); + } +} diff --git a/src/main/java/com/dnd/gongmuin/security/handler/CustomOauth2SuccessHandler.java b/src/main/java/com/dnd/gongmuin/security/handler/CustomOauth2SuccessHandler.java index 8a7a6a33..cc44d4e4 100644 --- a/src/main/java/com/dnd/gongmuin/security/handler/CustomOauth2SuccessHandler.java +++ b/src/main/java/com/dnd/gongmuin/security/handler/CustomOauth2SuccessHandler.java @@ -42,8 +42,8 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo Member findmember = memberRepository.findBySocialEmail(socialEmail) .orElseThrow(() -> new NotFoundException(MemberErrorCode.NOT_FOUND_MEMBER)); - String token = tokenProvider.generateAccessToken(customOauth2User, new Date()); - tokenProvider.generateRefreshToken(customOauth2User, new Date()); + String token = tokenProvider.generateAccessToken(findmember, customOauth2User, new Date()); + tokenProvider.generateRefreshToken(findmember, customOauth2User, new Date()); response.addCookie(cookieUtil.createCookie(token)); diff --git a/src/main/java/com/dnd/gongmuin/security/jwt/util/TokenProvider.java b/src/main/java/com/dnd/gongmuin/security/jwt/util/TokenProvider.java index fd4e25bc..c6fa454c 100644 --- a/src/main/java/com/dnd/gongmuin/security/jwt/util/TokenProvider.java +++ b/src/main/java/com/dnd/gongmuin/security/jwt/util/TokenProvider.java @@ -54,12 +54,12 @@ private void initSecretKey() { this.secretKey = Keys.hmacShaKeyFor(key.getBytes()); } - public String generateAccessToken(CustomOauth2User authentication, Date now) { - return generateToken(authentication, ACCESS_TOKEN_EXPIRE_TIME, now); + public String generateAccessToken(Member findMember, CustomOauth2User authentication, Date now) { + return generateToken(findMember, authentication, ACCESS_TOKEN_EXPIRE_TIME, now); } - public String generateRefreshToken(CustomOauth2User authentication, Date now) { - String refreshToken = generateToken(authentication, REFRESH_TOKEN_EXPIRE_TIME, now); + public String generateRefreshToken(Member findMember, CustomOauth2User authentication, Date now) { + String refreshToken = generateToken(findMember, authentication, REFRESH_TOKEN_EXPIRE_TIME, now); // redis Refresh 저장 redisUtil.setValues("RT:" + authentication.getEmail(), refreshToken, @@ -67,12 +67,12 @@ public String generateRefreshToken(CustomOauth2User authentication, Date now) { return refreshToken; } - private String generateToken(CustomOauth2User authentication, long tokenExpireTime, Date now) { + private String generateToken(Member findMember, CustomOauth2User authentication, long tokenExpireTime, Date now) { Date expiredTime = createExpiredDateWithTokenType(now, tokenExpireTime); String authorities = getAuthorities(authentication); return Jwts.builder() - .subject(authentication.getEmail()) + .subject(String.valueOf(findMember.getId())) .claim(ROLE_KEY, authorities) .issuedAt(now) .expiration(expiredTime) @@ -94,8 +94,8 @@ public Authentication getAuthentication(String token) { Claims claims = parseToken(token); List authorities = getAuthorities(claims); - String socialEmail = claims.getSubject(); - Member principal = memberRepository.findBySocialEmail(socialEmail) + String subject = claims.getSubject(); + Member principal = memberRepository.findById(Long.valueOf(subject)) .orElseThrow(() -> new NotFoundException(MemberErrorCode.NOT_FOUND_MEMBER)); return new UsernamePasswordAuthenticationToken(principal, token, authorities); diff --git a/src/test/java/com/dnd/gongmuin/answer/service/AnswerServiceTest.java b/src/test/java/com/dnd/gongmuin/answer/service/AnswerServiceTest.java index a1e18c38..d8395ce8 100644 --- a/src/test/java/com/dnd/gongmuin/answer/service/AnswerServiceTest.java +++ b/src/test/java/com/dnd/gongmuin/answer/service/AnswerServiceTest.java @@ -4,10 +4,15 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockito.BDDMockito.*; +import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -118,9 +123,9 @@ void chooseAnswer() { QuestionPost questionPost = QuestionPostFixture.questionPost(questionPostId, member); Answer answer = AnswerFixture.answer(1L, questionPostId); - given(answerRepository.findById(answer.getId())) + given(answerRepository.findByIdWithMember(answer.getId())) .willReturn(Optional.of(answer)); - given(questionPostRepository.findById(questionPost.getId())) + given(questionPostRepository.findByIdWithMember(questionPost.getId())) .willReturn(Optional.of(questionPost)); //when @@ -140,9 +145,9 @@ void chooseAnswer_fail() { ReflectionTestUtils.setField(questionPost, "reward", member.getCredit() + 1); Answer answer = AnswerFixture.answer(1L, questionPostId); - given(answerRepository.findById(answer.getId())) + given(answerRepository.findByIdWithMember(answer.getId())) .willReturn(Optional.of(answer)); - given(questionPostRepository.findById(questionPost.getId())) + given(questionPostRepository.findByIdWithMember(questionPost.getId())) .willReturn(Optional.of(questionPost)); //when & then @@ -162,9 +167,9 @@ void chooseAnswer_fail2() { QuestionPost questionPost = QuestionPostFixture.questionPost(questionPostId, questioner); Answer answer = AnswerFixture.answer(1L, questionPostId); - given(answerRepository.findById(answer.getId())) + given(answerRepository.findByIdWithMember(answer.getId())) .willReturn(Optional.of(answer)); - given(questionPostRepository.findById(questionPost.getId())) + given(questionPostRepository.findByIdWithMember(questionPost.getId())) .willReturn(Optional.of(questionPost)); //when & then @@ -172,4 +177,56 @@ void chooseAnswer_fail2() { .isInstanceOf(ValidationException.class) .hasMessageContaining(QuestionPostErrorCode.NOT_AUTHORIZED.getMessage()); } + + @Disabled + @DisplayName("[동시에 10_000개의 채택이 일어나 크레딧을 입금 받는다.]") + @Test + void creditHistoryWithOneHundred() throws Exception { + // given + final long threadCount = 10_000L; + final int writerCredit = 10_000_000; + ExecutorService executorService = Executors.newFixedThreadPool(32); + CountDownLatch latch = new CountDownLatch((int)threadCount); + + Member writer = MemberFixture.member(1L); + Member answer = MemberFixture.member(2L); + ReflectionTestUtils.setField(writer, "credit", writerCredit); + ReflectionTestUtils.setField(answer, "credit", 0); + + List questionPosts = new ArrayList<>(); + List answers = new ArrayList<>(); + + for (long i = 1L; i <= threadCount; i++) { + QuestionPost questionPost = QuestionPostFixture.questionPost(i, writer); + + Answer answer1 = AnswerFixture.answer(questionPost.getId(), answer); + ReflectionTestUtils.setField(answer1, "id", i); + questionPosts.add(questionPost); + answers.add(answer1); + + given(answerRepository.findByIdWithMember(i)).willReturn(Optional.of(answer1)); + given(questionPostRepository.findByIdWithMember(questionPost.getId())) + .willReturn(Optional.of(questionPost)); + } + + // when + long startTime = System.currentTimeMillis(); + for (long i = 0L; i < threadCount; i++) { + final int index = (int)i; + executorService.submit(() -> { + try { + answerService.chooseAnswer(answers.get(index).getId(), writer); + } finally { + latch.countDown(); + } + }); + } + latch.await(); + + long endTime = System.currentTimeMillis(); + System.out.println("Execution time: " + (endTime - startTime) + " ms"); + + // then + assertEquals(answer.getCredit(), writerCredit); + } } \ No newline at end of file diff --git a/src/test/java/com/dnd/gongmuin/auth/controller/AuthControllerTest.java b/src/test/java/com/dnd/gongmuin/auth/controller/AuthControllerTest.java index af976938..1a66656d 100644 --- a/src/test/java/com/dnd/gongmuin/auth/controller/AuthControllerTest.java +++ b/src/test/java/com/dnd/gongmuin/auth/controller/AuthControllerTest.java @@ -102,7 +102,7 @@ void signUp() throws Exception { savedMember.getSocialEmail(), savedMember.getRole() ); - String token = tokenProvider.generateAccessToken(new CustomOauth2User(authInfo), new Date()); + String token = tokenProvider.generateAccessToken(savedMember, new CustomOauth2User(authInfo), new Date()); this.loginMember = savedMember; this.accessToken = new Cookie("Authorization", token); diff --git a/src/test/java/com/dnd/gongmuin/auth/service/AuthServiceTest.java b/src/test/java/com/dnd/gongmuin/auth/service/AuthServiceTest.java index 41a4d086..58754cf0 100644 --- a/src/test/java/com/dnd/gongmuin/auth/service/AuthServiceTest.java +++ b/src/test/java/com/dnd/gongmuin/auth/service/AuthServiceTest.java @@ -174,10 +174,16 @@ void reissue() { given(cookieUtil.createCookie(anyString())).willReturn(new Cookie("Authorization", "reissueToken")); given(tokenProvider.getAuthentication(anyString())).willReturn(authentication); given(redisUtil.getValues(anyString())).willReturn("refreshToken"); - given(tokenProvider.generateAccessToken(any(CustomOauth2User.class), any(Date.class))).willReturn( - "reissueToken"); - given(tokenProvider.generateRefreshToken(any(CustomOauth2User.class), any(Date.class))).willReturn( - "reissueToken"); + given(tokenProvider.generateAccessToken( + any(Member.class), + any(CustomOauth2User.class), + any(Date.class))) + .willReturn("reissueToken"); + given(tokenProvider.generateRefreshToken( + any(Member.class), + any(CustomOauth2User.class), + any(Date.class))) + .willReturn("reissueToken"); // when ReissueResponse response = authService.reissue(mockRequest, mockResponse); diff --git a/src/test/java/com/dnd/gongmuin/chat/service/ChatRoomServiceTest.java b/src/test/java/com/dnd/gongmuin/chat/service/ChatRoomServiceTest.java index 67a03769..c00e2eaa 100644 --- a/src/test/java/com/dnd/gongmuin/chat/service/ChatRoomServiceTest.java +++ b/src/test/java/com/dnd/gongmuin/chat/service/ChatRoomServiceTest.java @@ -24,12 +24,10 @@ import com.dnd.gongmuin.chatroom.dto.response.ChatRoomInfo; import com.dnd.gongmuin.chatroom.dto.response.ChatRoomSimpleResponse; import com.dnd.gongmuin.chatroom.dto.response.LatestChatMessage; -import com.dnd.gongmuin.chatroom.exception.ChatErrorCode; import com.dnd.gongmuin.chatroom.repository.ChatMessageQueryRepository; import com.dnd.gongmuin.chatroom.repository.ChatMessageRepository; import com.dnd.gongmuin.chatroom.repository.ChatRoomRepository; import com.dnd.gongmuin.chatroom.service.ChatRoomService; -import com.dnd.gongmuin.common.exception.runtime.ValidationException; import com.dnd.gongmuin.common.fixture.ChatMessageFixture; import com.dnd.gongmuin.common.fixture.ChatRoomFixture; import com.dnd.gongmuin.common.fixture.MemberFixture; @@ -158,24 +156,4 @@ void getChatRoomById_Answerer() { .isEqualTo(inquirer.getId()) ); } - - @DisplayName("[채팅방에 속하지 않은 사람은 채팅방을 조회할 수 없다.]") - @Test - void getChatRoomById_Unauthorized() { - //given - Long chatRoomId = 1L; - Member inquirer = MemberFixture.member(1L); - Member answerer = MemberFixture.member(2L); - Member unrelatedMember = MemberFixture.member(3L); - QuestionPost questionPost = QuestionPostFixture.questionPost(inquirer); - ChatRoom chatRoom = ChatRoomFixture.chatRoom(questionPost, inquirer, answerer); - - given(chatRoomRepository.findById(chatRoomId)) - .willReturn(Optional.of(chatRoom)); - - //when & then - assertThatThrownBy(() -> chatRoomService.getChatRoomById(chatRoomId, unrelatedMember)) - .isInstanceOf(ValidationException.class) - .hasMessageContaining(ChatErrorCode.UNAUTHORIZED_CHAT_ROOM.getMessage()); - } } \ No newline at end of file diff --git a/src/test/java/com/dnd/gongmuin/chat_inquiry/controller/ChatInquiryControllerTest.java b/src/test/java/com/dnd/gongmuin/chat_inquiry/controller/ChatInquiryControllerTest.java index 992bffe2..4b3e0c88 100644 --- a/src/test/java/com/dnd/gongmuin/chat_inquiry/controller/ChatInquiryControllerTest.java +++ b/src/test/java/com/dnd/gongmuin/chat_inquiry/controller/ChatInquiryControllerTest.java @@ -57,6 +57,7 @@ void teardown() { creditHistoryRepository.deleteAll(); memberRepository.deleteAll(); questionPostRepository.deleteAll(); + chatInquiryRepository.deleteAll(); chatRoomRepository.deleteAll(); chatMessageRepository.deleteAll(); } @@ -82,6 +83,32 @@ void createChatInquiry() throws Exception { .andDo(MockMvcResultHandlers.print()); } + @DisplayName("[채팅 요청 아이디로 상세 채팅 요청을 조회할 수 있다.]") + @Test + void getChatInquiryById() throws Exception { + //given + Member chatPartner = memberRepository.save(MemberFixture.member5()); + QuestionPost questionPost = questionPostRepository.save(QuestionPostFixture.questionPost(loginMember)); + ChatInquiry chatInquiry = chatInquiryRepository.save( + ChatInquiryFixture.chatInquiry(questionPost, loginMember, chatPartner, INQUIRY_MESSAGE) + ); + + //when & then + mockMvc.perform(get("/api/chat/inquiries/{chatInquiryId}", chatInquiry.getId()) + .cookie(accessToken)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.chatInquiryId") + .value(chatInquiry.getId())) + .andExpect(jsonPath("$.inquiryStatus") + .value(InquiryStatus.PENDING.getLabel())) + .andExpect(jsonPath("$.chatPartner.memberId") + .value(chatPartner.getId())) + .andExpect(jsonPath("$.isInquirer") + .value(chatInquiry.getInquirer().equals(loginMember))) + .andExpect(jsonPath("$.inquiryStatus") + .value(InquiryStatus.PENDING.getLabel())); + } + @DisplayName("[회원의 채팅 요청 목록을 조회할 수 있다.]") @Test void getChatInquiresByMember() throws Exception { diff --git a/src/test/java/com/dnd/gongmuin/chat_inquiry/service/ChatInquiryServiceTest.java b/src/test/java/com/dnd/gongmuin/chat_inquiry/service/ChatInquiryServiceTest.java index 632bc320..e522871f 100644 --- a/src/test/java/com/dnd/gongmuin/chat_inquiry/service/ChatInquiryServiceTest.java +++ b/src/test/java/com/dnd/gongmuin/chat_inquiry/service/ChatInquiryServiceTest.java @@ -21,6 +21,7 @@ import com.dnd.gongmuin.chat_inquiry.domain.ChatInquiry; import com.dnd.gongmuin.chat_inquiry.domain.InquiryStatus; import com.dnd.gongmuin.chat_inquiry.dto.AcceptChatResponse; +import com.dnd.gongmuin.chat_inquiry.dto.ChatInquiryDetailResponse; import com.dnd.gongmuin.chat_inquiry.dto.ChatInquiryResponse; import com.dnd.gongmuin.chat_inquiry.dto.CreateChatInquiryRequest; import com.dnd.gongmuin.chat_inquiry.dto.CreateChatInquiryResponse; @@ -134,6 +135,23 @@ void createInquiry_fails() { .hasMessageContaining(MemberErrorCode.NOT_ENOUGH_CREDIT.getMessage()); } + @DisplayName("[채팅 요청 아이디로 채팅 요청 상세를 조회할 수 있다.]") + @Test + void getChatInquiryById() { + //given + Member inquirer = MemberFixture.member(1L); + Member answerer = MemberFixture.member(2L); + given(chatInquiryRepository.findById(1L)) + .willReturn(Optional.of(ChatInquiryFixture.chatInquiry( + 1L, QuestionPostFixture.questionPost(inquirer), inquirer, answerer, INQUIRY_MESSAGE) + )); + //when + ChatInquiryDetailResponse response = chatInquiryService.getChatInquiryById(1L, inquirer); + + //then + assertThat(response.chatPartner().memberId()).isEqualTo(answerer.getId()); + } + @DisplayName("[회원이 속한 채팅 요청 목록을 조회할 수 있다.]") @Test void getChatInquiresByMember() { @@ -141,10 +159,10 @@ void getChatInquiresByMember() { Long chatInquiryId = 1L; Member targetMember = MemberFixture.member(1L); Member partner = MemberFixture.member(2L); - ChatInquiryResponse chatInquiryResponse = new ChatInquiryResponse( - chatInquiryId, INQUIRY_MESSAGE, InquiryStatus.PENDING, true, partner.getId(), - partner.getNickname(), partner.getJobGroup(), partner.getProfileImageNo() + ChatInquiry chatInquiry = ChatInquiryFixture.chatInquiry( + 1L, QuestionPostFixture.questionPost(targetMember), targetMember, partner, INQUIRY_MESSAGE ); + ChatInquiryResponse chatInquiryResponse = new ChatInquiryResponse(chatInquiry, true); given(chatInquiryRepository.getChatInquiresByMember(targetMember, pageRequest)) .willReturn(new SliceImpl<>(List.of(chatInquiryResponse), pageRequest, false)); @@ -238,8 +256,7 @@ void rejectChat() { RejectChatResponse response = chatInquiryService.rejectChat(chatInquiryId, answerer); //then - assertThat(response.inquiryStatus()) - .isEqualTo(InquiryStatus.REJECTED.getLabel()); + assertThat(response.inquiryStatus()).isEqualTo(InquiryStatus.REJECTED.getLabel()); } @DisplayName("[답변자가 채팅 요청을 거절할 때 채팅 거절 알림이 발행된다.]") diff --git a/src/test/java/com/dnd/gongmuin/common/fixture/ChatInquiryFixture.java b/src/test/java/com/dnd/gongmuin/common/fixture/ChatInquiryFixture.java index 4cd9a170..e9ce9079 100644 --- a/src/test/java/com/dnd/gongmuin/common/fixture/ChatInquiryFixture.java +++ b/src/test/java/com/dnd/gongmuin/common/fixture/ChatInquiryFixture.java @@ -1,5 +1,7 @@ package com.dnd.gongmuin.common.fixture; +import java.time.LocalDateTime; + import org.springframework.test.util.ReflectionTestUtils; import com.dnd.gongmuin.chat_inquiry.domain.ChatInquiry; @@ -40,6 +42,7 @@ public static ChatInquiry chatInquiry( message ); ReflectionTestUtils.setField(chatInquiry, "id", id); + ReflectionTestUtils.setField(chatInquiry, "createdAt", LocalDateTime.now()); return chatInquiry; } } diff --git a/src/test/java/com/dnd/gongmuin/common/support/ApiTestSupport.java b/src/test/java/com/dnd/gongmuin/common/support/ApiTestSupport.java index 95ba1283..cafb82f5 100644 --- a/src/test/java/com/dnd/gongmuin/common/support/ApiTestSupport.java +++ b/src/test/java/com/dnd/gongmuin/common/support/ApiTestSupport.java @@ -54,8 +54,8 @@ public void setUpMember() { savedMember.getSocialEmail(), savedMember.getRole() ); - String token = tokenProvider.generateAccessToken(new CustomOauth2User(authInfo), new Date()); - tokenProvider.generateRefreshToken(new CustomOauth2User(authInfo), new Date()); + String token = tokenProvider.generateAccessToken(savedMember, new CustomOauth2User(authInfo), new Date()); + tokenProvider.generateRefreshToken(savedMember, new CustomOauth2User(authInfo), new Date()); this.loginMember = savedMember; this.accessToken = cookieUtil.createCookie(token); } diff --git a/src/test/java/com/dnd/gongmuin/security/jwt/TokenProviderTest.java b/src/test/java/com/dnd/gongmuin/security/jwt/TokenProviderTest.java index 7dcd84d0..b15ca57e 100644 --- a/src/test/java/com/dnd/gongmuin/security/jwt/TokenProviderTest.java +++ b/src/test/java/com/dnd/gongmuin/security/jwt/TokenProviderTest.java @@ -66,7 +66,7 @@ void generateAccessToken() { CustomOauth2User authentication = new CustomOauth2User(authInfo); // when - String accessToken = tokenProvider.generateAccessToken(authentication, now); + String accessToken = tokenProvider.generateAccessToken(MemberFixture.member(1L), authentication, now); Claims claims = Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(accessToken).getPayload(); Date expiration = claims.getExpiration(); @@ -85,7 +85,7 @@ void generateRefreshToken() { CustomOauth2User authentication = new CustomOauth2User(authInfo); // when - String accessToken = tokenProvider.generateRefreshToken(authentication, now); + String accessToken = tokenProvider.generateRefreshToken(MemberFixture.member(1L), authentication, now); Claims claims = Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(accessToken).getPayload(); Date expiration = claims.getExpiration(); @@ -93,17 +93,17 @@ void generateRefreshToken() { assertThat(expiration.getTime()).isCloseTo(expectedExpirationTime, within(1000L)); } - @DisplayName("토큰 파싱을 통해 만들어진 인증 객체의 이메일은 토큰 정보의 이메일 값과 동일하다.") + @DisplayName("토큰 파싱을 통해 만들어진 인증 객체의 이메일은 회원 이메일과 동일하다.") @Test void getAuthentication() { // given Date now = new Date(); - Member member = MemberFixture.member(); + Member member = MemberFixture.member(1L); CustomOauth2User customOauth2User = new CustomOauth2User(authInfo); - String accessToken = tokenProvider.generateAccessToken(customOauth2User, now); + String accessToken = tokenProvider.generateAccessToken(member, customOauth2User, now); - given(memberRepository.findBySocialEmail(anyString())).willReturn(Optional.ofNullable(member)); + given(memberRepository.findById(anyLong())).willReturn(Optional.ofNullable(member)); // when Authentication authentication = tokenProvider.getAuthentication(accessToken); @@ -121,7 +121,7 @@ void validateToken() { Date past = new Date(124, 6, 30, 16, 0, 0); CustomOauth2User customOauth2User = new CustomOauth2User(authInfo); - String accessToken = tokenProvider.generateRefreshToken(customOauth2User, past); + String accessToken = tokenProvider.generateRefreshToken(MemberFixture.member(1L), customOauth2User, past); // when boolean result = tokenProvider.validateToken(accessToken, new Date());