Skip to content

[BE] 알림 목록 조회, 상대 프로필, 채팅 요청 수정(#98) #103

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

Merged
merged 21 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
1d64320
feat: 알림 응답 DTO, 추상 클래스로 전환(#98)
Minjae-An May 26, 2024
3c98bb8
feat: 단순 알림 응답 DTO 추가(#98)
Minjae-An May 26, 2024
35f5621
feat: 채팅 요청 알림 응답 DTO 추가(#98)
Minjae-An May 26, 2024
e909bb5
feat: 응답 생성 메서드, 외부에서 알림 응답 목록 전달받도록 변경(#98)
Minjae-An May 26, 2024
a1424c0
feat: 채팅방 존재 여부 확인 로직 정의(#98)
Minjae-An May 26, 2024
63267b4
feat: 채팅방 존재 여부 확인 로직 추가(#98)
Minjae-An May 26, 2024
53b24c4
feat: 알림 목록 조회시, 알림 응답 DTO 매핑 로직 추가(#98)
Minjae-An May 26, 2024
3072fd8
feat: 불필요한 알림 보낸 사용자 닉네임 제거(#98)
Minjae-An May 27, 2024
f06ac14
Merge branch 'dev' into feat/#98-chatting-requested-notification
Minjae-An May 29, 2024
6327c7a
feat: 채팅 수락 알림 여부 확인 로직 추가(#98)
Minjae-An May 29, 2024
6c366d6
feat: 채팅 요청 알림 응답 DTO 변경(#98)
Minjae-An May 29, 2024
7a7324d
feat: 불필요한 채팅방 존재 여부 확인 로직 삭제(#98)
Minjae-An May 29, 2024
21763bb
feat: 알림 응답 DTO 매핑 로직 수정(#98)
Minjae-An May 29, 2024
1f61a49
feat: 채팅 수락 알림 응답 DTO 추가(#98)
Minjae-An May 29, 2024
27da8f1
feat: 다른 사용자 프로필 조회시, 채팅 가능 여부 포함(#98)
Minjae-An May 29, 2024
01fc677
feat: 사용자 기반 채팅방 존재 여부 확인 로직 추가(#98)
Minjae-An May 29, 2024
02a35ac
feat: 다른 사용자 프로필 조회시 채팅 가능 여부 응답에 포함(#98)
Minjae-An May 29, 2024
a46584d
feat: 채팅방 존재 여부 확인 로직 추가(#98)
Minjae-An May 29, 2024
07fda29
feat: 이미 채팅 중인 사용자 예외 추가(#98)
Minjae-An May 29, 2024
a3161b2
feat: 채팅 요청시 이미 채팅 중인 사용자인 지 검증(#98)
Minjae-An May 29, 2024
9b678d2
feat: 잘못된 검증 로직 수정(#98)
Minjae-An May 29, 2024
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 @@ -31,4 +31,9 @@ public ChatRoom findBy(User sender, User receiver) {
return chatRoomRepository.findBySenderAndReceiver(sender, receiver)
.orElseThrow(() -> new GeneralException(NOT_FOUND_CHAT_ROOM));
}

public boolean existsBy(User sender, User receiver) {

return chatRoomRepository.existsBySenderAndReceiverAndActiveIsTrue(sender, receiver);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
import yeonba.be.user.entity.User;

@Repository
public interface ChatRoomRepository extends JpaRepository<ChatRoom, Long>, ChatRoomRepositoryCustom {
public interface ChatRoomRepository extends JpaRepository<ChatRoom, Long>,
ChatRoomRepositoryCustom {

Optional<ChatRoom> findBySenderAndReceiver(User sender, User receiver);

boolean existsBySenderAndReceiverAndActiveIsTrue(User sender, User receiver);
}
8 changes: 7 additions & 1 deletion be/src/main/java/yeonba/be/chatting/service/ChatService.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import yeonba.be.chatting.repository.chatmessage.ChatMessageQuery;
import yeonba.be.chatting.repository.chatroom.ChatRoomCommand;
import yeonba.be.chatting.repository.chatroom.ChatRoomQuery;
import yeonba.be.chatting.repository.chatroom.ChatRoomRepository;
import yeonba.be.exception.BlockException;
import yeonba.be.exception.ChatException;
import yeonba.be.exception.GeneralException;
Expand Down Expand Up @@ -125,6 +124,13 @@ public void requestChat(long senderId, long receiverId) {
throw new GeneralException(BlockException.ALREADY_BLOCKED_USER);
}

// 이미 채팅 중인 사용자인 지 검증
boolean chatRoomExist =
chatRoomQuery.existsBy(sender, receiver) || chatRoomQuery.existsBy(receiver, sender);
if (chatRoomExist) {
throw new GeneralException(ChatException.ALREADY_CHAT_USER);
}

// 비활성화된 채팅방 생성
chatRoomCommand.createChatRoom(new ChatRoom(sender, receiver));

Expand Down
6 changes: 5 additions & 1 deletion be/src/main/java/yeonba/be/exception/ChatException.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ public enum ChatException implements BaseException {

NOT_FOUND_CHAT_ROOM(
HttpStatus.BAD_REQUEST,
"요청된 채팅방이 없습니다.");
"요청된 채팅방이 없습니다."),

ALREADY_CHAT_USER(
HttpStatus.BAD_REQUEST,
"이미 채팅 중인 사용자입니다.");

private final HttpStatus httpStatus;
private final String reason;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package yeonba.be.notification.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
import lombok.Getter;
import yeonba.be.notification.entity.Notification;
import yeonba.be.user.entity.User;

@Getter
public class ChattingAcceptedNotificationResponse extends NotificationResponse {

@Schema(
type = "number",
description = "채팅방 ID",
example = "1")
private long chatRoomId;

public ChattingAcceptedNotificationResponse(
String notificationType,
String content,
long senderId,
String senderProfilePhotoUrl,
LocalDateTime createdAt,
long chatRoomId) {

super(notificationType, content, senderId, senderProfilePhotoUrl, createdAt);
this.chatRoomId = chatRoomId;
}

public static ChattingAcceptedNotificationResponse from(Notification notification,
long chatRoomId) {

User sender = notification.getSender();

return new ChattingAcceptedNotificationResponse(
notification.getType().name(),
notification.getContent(),
sender.getId(),
sender.getRepresentativeProfilePhoto(),
notification.getCreatedAt(),
chatRoomId
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package yeonba.be.notification.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
import lombok.Getter;
import yeonba.be.notification.entity.Notification;
import yeonba.be.user.entity.User;

@Getter
public class ChattingRequestedNotificationResponse extends NotificationResponse {

@Schema(
type = "number",
description = "알림 ID",
example = "1")
private long notificationId;

public ChattingRequestedNotificationResponse(
String notificationType,
String content,
long senderId,
String senderProfilePhotoUrl,
LocalDateTime createdAt,
long notificationId) {

super(notificationType, content, senderId, senderProfilePhotoUrl, createdAt);
this.notificationId = notificationId;
}

public static ChattingRequestedNotificationResponse from(Notification notification) {

User sender = notification.getSender();

return new ChattingRequestedNotificationResponse(
notification.getType().name(),
notification.getContent(),
sender.getId(),
sender.getRepresentativeProfilePhoto(),
notification.getCreatedAt(),
notification.getId()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,11 @@ public class NotificationPageResponse {
@JsonProperty("isLast")
private boolean last;

public static NotificationPageResponse from(Page<Notification> page) {

List<NotificationResponse> content = page.getContent().stream()
.map(NotificationResponse::from)
.toList();
public static NotificationPageResponse from(Page<Notification> page,
List<NotificationResponse> notifications) {

return new NotificationPageResponse(
content,
notifications,
page.getTotalPages(),
page.getTotalElements(),
page.isFirst(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,18 @@
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Getter;
import yeonba.be.notification.entity.Notification;
import yeonba.be.user.entity.User;

@Getter
@AllArgsConstructor
public class NotificationResponse {
public abstract class NotificationResponse {

@Schema(
type = "string",
description = """
알림 타입, 다음 종류 존재
- ARROW_RECEIVED (화살 수신)
- CHAT_REQUESTED (채팅 요청 수신)
- CHAT_REQUEST_ACCEPTED (요청한 채팅 수락됨)""",
- CHATTING_REQUESTED (채팅 요청 수신)
- CHATTING_REQUEST_ACCEPTED (요청한 채팅 수락됨)""",
example = "ARROW_RECEIVED")
private String notificationType;

Expand All @@ -39,29 +37,9 @@ public class NotificationResponse {
example = "profile-photo/1-0")
private String senderProfilePhotoUrl;

@Schema(
type = "string",
description = "알림 보낸 사용자 별명",
example = "안민재")
private String senderNickname;

@Schema(
type = "string",
description = "알림 생성 일시",
example = "2024-04-10 10:12:00.112233")
private LocalDateTime createdAt;

public static NotificationResponse from(Notification notification) {

User sender = notification.getSender();

return new NotificationResponse(
notification.getType().name(),
notification.getContent(),
sender.getId(),
sender.getRepresentativeProfilePhoto(),
sender.getNickname(),
notification.getCreatedAt()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package yeonba.be.notification.dto.response;

import java.time.LocalDateTime;
import yeonba.be.notification.entity.Notification;
import yeonba.be.user.entity.User;

public class SimpleNotificationResponse extends NotificationResponse {

public SimpleNotificationResponse(
String notificationType,
String content,
long senderId,
String senderProfilePhotoUrl,
LocalDateTime createdAt) {

super(notificationType, content, senderId, senderProfilePhotoUrl, createdAt);
}

public static SimpleNotificationResponse from(Notification notification) {

User sender = notification.getSender();

return new SimpleNotificationResponse(
notification.getType().name(),
notification.getContent(),
sender.getId(),
sender.getRepresentativeProfilePhoto(),
notification.getCreatedAt()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@ public boolean isChattingRequest() {

return this == CHATTING_REQUESTED;
}

public boolean isChattingAccept() {

return this == CHATTING_REQUEST_ACCEPTED;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,17 @@
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import yeonba.be.chatting.entity.ChatRoom;
import yeonba.be.chatting.repository.chatroom.ChatRoomQuery;
import yeonba.be.exception.GeneralException;
import yeonba.be.exception.NotificationException;
import yeonba.be.notification.dto.request.NotificationPageRequest;
import yeonba.be.notification.dto.response.ChattingAcceptedNotificationResponse;
import yeonba.be.notification.dto.response.ChattingRequestedNotificationResponse;
import yeonba.be.notification.dto.response.NotificationPageResponse;
import yeonba.be.notification.dto.response.NotificationResponse;
import yeonba.be.notification.dto.response.NotificationUnreadExistResponse;
import yeonba.be.notification.dto.response.SimpleNotificationResponse;
import yeonba.be.notification.entity.Notification;
import yeonba.be.notification.entity.NotificationPermission;
import yeonba.be.notification.enums.NotificationType;
Expand All @@ -32,6 +38,7 @@ public class NotificationService {
private final UserQuery userQuery;
private final NotificationQuery notificationQuery;
private final NotificationPermissionQuery notificationPermissionQuery;
private final ChatRoomQuery chatRoomQuery;

private final NotificationCommand notificationCommand;
private final NotificationPermissionCommand notificationPermissionCommand;
Expand All @@ -52,17 +59,42 @@ public NotificationPageResponse getRecentlyReceivedNotificationsBy(
User receiver = userQuery.findById(receiverId);
Page<Notification> page =
notificationQuery.findRecentlyReceivedNotificationsBy(receiver, pageRequest);
List<Notification> notifications = page.getContent();

// 가장 최근에 받은 알림 ID 도출
long mostRecentNotificationId = page.getContent().stream()
long mostRecentNotificationId = notifications.stream()
.mapToLong(Notification::getId)
.max()
.orElse(Long.MAX_VALUE);

// 가장 최근에 받은 알림 포함 이전 알림 전부 읽음 처리
notificationCommand.readNotificationsUpToIdBy(receiverId, mostRecentNotificationId);

return NotificationPageResponse.from(page);
List<NotificationResponse> response = notifications.stream()
.map(this::toNotificationResponse)
.toList();

return NotificationPageResponse.from(page, response);
}

private NotificationResponse toNotificationResponse(Notification notification) {

NotificationType type = notification.getType();

if (type.isChattingAccept()) {

ChatRoom chatRoom = chatRoomQuery.findBy(notification.getReceiver(),
notification.getSender());

return ChattingAcceptedNotificationResponse.from(notification, chatRoom.getId());
}

if (type.isChattingRequest()) {

return ChattingRequestedNotificationResponse.from(notification);
}

return SimpleNotificationResponse.from(notification);
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package yeonba.be.user.dto.response;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.AllArgsConstructor;
Expand Down Expand Up @@ -112,8 +113,15 @@ public class UserProfileResponse {
example = "false")
private boolean isAlreadySentArrow;

@Schema(
type = "boolean",
description = "채팅 요청 가능 여부",
example = "false")
@JsonProperty("canChat")
private boolean canChat;

public static UserProfileResponse from(
User user, UserPreference userPreference, boolean isAlreadySentArrow) {
User user, UserPreference userPreference, boolean isAlreadySentArrow, boolean canChat) {

return new UserProfileResponse(
user.getProfilePhotoUrls(),
Expand All @@ -132,7 +140,8 @@ public static UserProfileResponse from(
userPreference.getHeightUpperBound(),
userPreference.getMbti(),
userPreference.getBodyType(),
isAlreadySentArrow
isAlreadySentArrow,
canChat
);
}
}
Loading
Loading