Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
import com.assu.server.domain.chat.dto.ChatResponseDTO;
import com.assu.server.domain.chat.service.ChatService;
import com.assu.server.global.apiPayload.code.status.SuccessStatus;
import com.assu.server.global.util.PrincipalDetails;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import com.assu.server.global.apiPayload.BaseResponse;
import org.springframework.messaging.simp.SimpMessagingTemplate;
Expand All @@ -22,26 +24,38 @@ public class ChatController {
private final SimpMessagingTemplate simpMessagingTemplate;

@Operation(
summary = "채팅방 목록 조회 API",
description = "Request Header에 User id를 입력해 주세요."
summary = "채팅방을 생성하는 API",
description = "# [v1.0 (2025-08-05)](https://clumsy-seeder-416.notion.site/2241197c19ed80c38871ec77deced713) 채팅방을 생성합니다.\n"+
"- storeId: Request Body, Long\n" +
"- partnerId: Request Body, Long\n"
)
@GetMapping("/rooms")
public BaseResponse<List<com.assu.server.domain.chat.dto.ChatRoomListResultDTO>> getChatRoomList() {
return BaseResponse.onSuccess(SuccessStatus._OK, chatService.getChatRoomList());
@PostMapping("/create/rooms")
public BaseResponse<ChatResponseDTO.CreateChatRoomResponseDTO> createChatRoom(
@AuthenticationPrincipal PrincipalDetails pd,
@RequestBody ChatRequestDTO.CreateChatRoomRequestDTO request) {
Long memberId = pd.getMember().getId();
return BaseResponse.onSuccess(SuccessStatus._OK, chatService.createChatRoom(request, memberId));
}

@Operation(
summary = "채팅방 생성 API",
description = "상대방의 id를 request body에 입력해 주세요"
summary = "채팅방 목록을 조회하는 API",
description = "# [v1.0 (2025-08-05)](https://clumsy-seeder-416.notion.site/API-1d71197c19ed819f8f70fb437e9ce62b?p=2241197c19ed816993c3c5ae17d6f099&pm=s) 채팅방 목록을 조회합니다.\n"
)
@PostMapping("/create/rooms")
public BaseResponse<ChatResponseDTO.CreateChatRoomResponseDTO> createChatRoom(@RequestBody ChatRequestDTO.CreateChatRoomRequestDTO request) {
return BaseResponse.onSuccess(SuccessStatus._OK, chatService.createChatRoom(request));
@GetMapping("/rooms")
public BaseResponse<List<com.assu.server.domain.chat.dto.ChatRoomListResultDTO>> getChatRoomList(
@AuthenticationPrincipal PrincipalDetails pd
) {
Long memberId = pd.getMember().getId();
return BaseResponse.onSuccess(SuccessStatus._OK, chatService.getChatRoomList(memberId));
}

@Operation(
summary = "채팅 API",
description = "roomId, senderId, message를 입력해 주세요"
description = "# [v1.0 (2025-08-05)](https://clumsy-seeder-416.notion.site/2241197c19ed800eab45c35073761c97?v=2241197c19ed8134b64f000cc26c5d31&p=2371197c19ed80968342e2bc8fe88cee&pm=s) 메시지를 전송합니다.\n"+
"- roomId: Request Body, Long\n" +
"- senderId: Request Body, Long\n"+
"- receiverId: Request Body, Long\n" +
"- message: Request Body, String\n"
)
@MessageMapping("/send")
public void handleMessage(@Payload ChatRequestDTO.ChatMessageRequestDTO request) {
Expand All @@ -52,34 +66,46 @@ public void handleMessage(@Payload ChatRequestDTO.ChatMessageRequestDTO request)

@Operation(
summary = "메시지 읽음 처리 API",
description = "roomId를 입력해 주세요."
description = "# [v1.0 (2025-08-05)](https://clumsy-seeder-416.notion.site/2241197c19ed800eab45c35073761c97?v=2241197c19ed8134b64f000cc26c5d31&p=2241197c19ed81ffa771cb18ab157b54&pm=s) 메시지를 읽음처리합니다.\n"+
"- roomId: Path Variable, Long\n"
)
@PatchMapping("rooms/{roomId}/read")
public BaseResponse<ChatResponseDTO.ReadMessageResponseDTO> readMessage(
@PathVariable Long roomId) {
ChatResponseDTO.ReadMessageResponseDTO response = chatService.readMessage(roomId);
@AuthenticationPrincipal PrincipalDetails pd,
@PathVariable Long roomId
) {
Long memberId = pd.getMember().getId();
ChatResponseDTO.ReadMessageResponseDTO response = chatService.readMessage(roomId, memberId);
return BaseResponse.onSuccess(SuccessStatus._OK, response);
}

@Operation(
summary = "채팅방 상세 조회 API",
description = "roomId를 입력해 주세요."
description = "# [v1.0 (2025-08-05)](https://clumsy-seeder-416.notion.site/2241197c19ed800eab45c35073761c97?v=2241197c19ed8134b64f000cc26c5d31&p=2241197c19ed81399395fd66f73730af&pm=s) 채팅방을 클릭했을 때 메시지를 조회합니다.\n"+
"- roomId: Path Variable, Long\n"
)
@GetMapping("rooms/{roomId}/messages")
public BaseResponse<ChatResponseDTO.ChatHistoryResponseDTO> getChatHistory(@PathVariable Long roomId) {
ChatResponseDTO.ChatHistoryResponseDTO response = chatService.readHistory(roomId);
public BaseResponse<ChatResponseDTO.ChatHistoryResponseDTO> getChatHistory(
@AuthenticationPrincipal PrincipalDetails pd,
@PathVariable Long roomId
) {
Long memberId = pd.getMember().getId();
ChatResponseDTO.ChatHistoryResponseDTO response = chatService.readHistory(roomId, memberId);
return BaseResponse.onSuccess(SuccessStatus._OK, response);
}

@Operation(
summary = "채팅방 나가기 API" +
" (참여자가 2명이면 채팅방이 살아있지만, 이미 한 명이 나갔다면 채팅방이 삭제됩니다.)",
description = "roomId를 입력해 주세요."
summary = "채팅방을 나가는 API" +
"참여자가 2명이면 채팅방이 살아있지만, 이미 한 명이 나갔다면 채팅방이 삭제됩니다.",
description = "# [v1.0 (2025-08-05)](https://clumsy-seeder-416.notion.site/2241197c19ed800eab45c35073761c97?v=2241197c19ed8134b64f000cc26c5d31&p=2371197c19ed8079a6e1c2331cb4f534&pm=s) 채팅방을 나갑니다.\n"+
"- roomId: Path Variable, Long\n"
)
@DeleteMapping("rooms/{roomId}/leave")
public BaseResponse<ChatResponseDTO.LeaveChattingRoomResponseDTO> leaveChattingRoom(
@AuthenticationPrincipal PrincipalDetails pd,
@PathVariable Long roomId
) {
return BaseResponse.onSuccess(SuccessStatus._OK, chatService.leaveChattingRoom(roomId));
Long memberId = pd.getMember().getId();
return BaseResponse.onSuccess(SuccessStatus._OK, chatService.leaveChattingRoom(roomId, memberId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
public class ChatRequestDTO {
@Getter
public static class CreateChatRoomRequestDTO {
private Long adminId;
private Long storeId;
private Long partnerId;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
import java.util.List;

public interface ChatService {
List<ChatRoomListResultDTO> getChatRoomList();
ChatResponseDTO.CreateChatRoomResponseDTO createChatRoom(ChatRequestDTO.CreateChatRoomRequestDTO request);
List<ChatRoomListResultDTO> getChatRoomList(Long memberId);
ChatResponseDTO.CreateChatRoomResponseDTO createChatRoom(ChatRequestDTO.CreateChatRoomRequestDTO request, Long memberId);
ChatResponseDTO.SendMessageResponseDTO handleMessage(ChatRequestDTO.ChatMessageRequestDTO request);
ChatResponseDTO.ReadMessageResponseDTO readMessage(Long roomId);
ChatResponseDTO.ChatHistoryResponseDTO readHistory(Long roomId);
ChatResponseDTO.LeaveChattingRoomResponseDTO leaveChattingRoom(Long roomId);
ChatResponseDTO.ReadMessageResponseDTO readMessage(Long roomId, Long memberId);
ChatResponseDTO.ChatHistoryResponseDTO readHistory(Long roomId, Long memberId);
ChatResponseDTO.LeaveChattingRoomResponseDTO leaveChattingRoom(Long roomId, Long memberId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import com.assu.server.domain.member.repository.MemberRepository;
import com.assu.server.domain.partner.entity.Partner;
import com.assu.server.domain.partner.repository.PartnerRepository;
import com.assu.server.domain.store.entity.Store;
import com.assu.server.domain.store.repository.StoreRepository;
import com.assu.server.global.apiPayload.code.status.ErrorStatus;
import com.assu.server.global.exception.DatabaseException;
import jakarta.transaction.Transactional;
Expand All @@ -31,29 +33,33 @@ public class ChatServiceImpl implements ChatService {
private final PartnerRepository partnerRepository;
private final AdminRepository adminRepository;
private final MessageRepository messageRepository;
private final StoreRepository storeRepository;


@Override
public List<ChatRoomListResultDTO> getChatRoomList() {
// Long memberId = SecurityUtil.getCurrentUserId;
Long memberId = 1L;
public List<ChatRoomListResultDTO> getChatRoomList(Long memberId) {

List<ChatRoomListResultDTO> chatRoomList = chatRepository.findChattingRoomsByMemberId(memberId);
return ChatConverter.toChatRoomListResultDTO(chatRoomList);
}

@Override
public ChatResponseDTO.CreateChatRoomResponseDTO createChatRoom(ChatRequestDTO.CreateChatRoomRequestDTO request) {
// Long memberId = SecurityUtil.getCurrentUserId;
// Long opponentId = request.getOpponentId();
public ChatResponseDTO.CreateChatRoomResponseDTO createChatRoom(ChatRequestDTO.CreateChatRoomRequestDTO request, Long memberId) {

Long adminId = request.getAdminId();
Long storeId = request.getStoreId();
Long partnerId = request.getPartnerId();

Admin admin = adminRepository.findById(adminId)
Admin admin = adminRepository.findById(memberId)
.orElseThrow(() -> new DatabaseException(ErrorStatus.NO_SUCH_ADMIN));
Partner partner = partnerRepository.findById(partnerId)
.orElseThrow(() -> new DatabaseException(ErrorStatus.NO_SUCH_PARTNER));
Store store = storeRepository.findById(storeId)
.orElseThrow(() -> new DatabaseException(ErrorStatus.NO_SUCH_STORE));


if (!store.getPartner().getMember().getId().equals(partner.getMember().getId())) {
throw new DatabaseException(ErrorStatus.NO_SUCH_STORE_WITH_THAT_PARTNER);
}

ChattingRoom room = ChatConverter.toCreateChattingRoom(admin, partner);

Expand All @@ -66,9 +72,6 @@ public ChatResponseDTO.CreateChatRoomResponseDTO createChatRoom(ChatRequestDTO.C
admin.getName()
);
ChattingRoom savedRoom = chatRepository.save(room);



return ChatConverter.toCreateChatRoomIdDTO(savedRoom);
}

Expand All @@ -90,9 +93,7 @@ public ChatResponseDTO.SendMessageResponseDTO handleMessage(ChatRequestDTO.ChatM

@Transactional
@Override
public ChatResponseDTO.ReadMessageResponseDTO readMessage(Long roomId) {
// Long memberId = SecurityUtil.getCurrentUserId();
Long memberId = 2L;
public ChatResponseDTO.ReadMessageResponseDTO readMessage(Long roomId, Long memberId) {

List<Message> unreadMessages = messageRepository.findUnreadMessagesByRoomAndReceiver(roomId, memberId);

Expand All @@ -102,24 +103,18 @@ public ChatResponseDTO.ReadMessageResponseDTO readMessage(Long roomId) {
}

@Override
public ChatResponseDTO.ChatHistoryResponseDTO readHistory(Long roomId) {
// Long memberId = SecurityUtil.getCurrentUserId();
Long memberId = 1L;
public ChatResponseDTO.ChatHistoryResponseDTO readHistory(Long roomId, Long memberId) {

ChattingRoom room = chatRepository.findById(roomId)
.orElseThrow(() -> new DatabaseException(ErrorStatus.NO_SUCH_ROOM));

List<ChatMessageDTO> allMessages = messageRepository.findAllMessagesByRoomAndMemberId(roomId, memberId);
List<ChatMessageDTO> allMessages = messageRepository.findAllMessagesByRoomAndMemberId(room.getId(), memberId);

return ChatConverter.toChatHistoryDTO(roomId, allMessages);
return ChatConverter.toChatHistoryDTO(room.getId(), allMessages);
}

@Override
public ChatResponseDTO.LeaveChattingRoomResponseDTO leaveChattingRoom(Long roomId) {
// Long memberId = SecurityUtil.getCurrentUserId();

Long memberId = 2L;

public ChatResponseDTO.LeaveChattingRoomResponseDTO leaveChattingRoom(Long roomId, Long memberId) {
// 멤버 조회
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new DatabaseException(ErrorStatus.NO_SUCH_MEMBER));
Expand Down
12 changes: 2 additions & 10 deletions src/main/java/com/assu/server/domain/store/entity/Store.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,7 @@
import com.assu.server.domain.common.enums.ActivationStatus;
import com.assu.server.domain.partner.entity.Partner;

import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;
Expand All @@ -28,7 +20,7 @@ public class Store extends BaseEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "partner_id")
private Partner partner;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,12 @@ public enum ErrorStatus implements BaseErrorCode {
NO_SUCH_STUDENT(HttpStatus.NOT_FOUND,"MEMBER_4004","존재하지 않는 student ID 입니다."),
NO_SUCH_STORE(HttpStatus.NOT_FOUND, "STORE_4006", "존재하지 않는 스토어 ID입니다."),
NO_PAPER_FOR_STORE(HttpStatus.NOT_FOUND, "ADMIN_4005", "존재하지 않는 paper ID입니다."),
EXISTED_PHONE(HttpStatus.NOT_FOUND,"MEMBER_4005","이미 존재하는 전화번호입니다."),
EXISTED_EMAIL(HttpStatus.NOT_FOUND,"MEMBER_4006","이미 존재하는 이메일입니다."),
EXISTED_STUDENT(HttpStatus.NOT_FOUND,"MEMBER_4007","이미 존재하는 학번입니다."),
NO_AVAILABLE_PARTNER(HttpStatus.NOT_FOUND, "MEMBER_4009", "제휴업체를 찾을 수 없습니다."),
NO_SUCH_STORE_WITH_THAT_PARTNER(HttpStatus.NOT_FOUND,"MEMBER_4006","해당 store ID에 해당하는 partner ID가 존재하지 않습니다."),
EXISTED_PHONE(HttpStatus.NOT_FOUND,"MEMBER_4007","이미 존재하는 전화번호입니다."),
EXISTED_EMAIL(HttpStatus.NOT_FOUND,"MEMBER_4008","이미 존재하는 이메일입니다."),
EXISTED_STUDENT(HttpStatus.NOT_FOUND,"MEMBER_4009","이미 존재하는 학번입니다."),


// 제휴 에러
NO_SUCH_PAPER(HttpStatus.NOT_FOUND, "PAPER_9001", "제휴를 찾을 수 없습니다."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Getter
@Builder
Expand Down