Skip to content

Commit

Permalink
feat/dummy-1: 서버 재시작마다 자동으로 dummyData가 생성됨 (#179)
Browse files Browse the repository at this point in the history
* fix/community-1: 게시글 조회 응답 DTO에 댓글 갯수를 표시한다.
- 단일 게시글 조회 시 / 게시글 그룹별 조회 시 댓글 갯수는 응답 DTO에 포함된다.

* fix/community-2: 댓글 조회시 본인이 종속되어 있는 게시글의 정보가 응답 DTO에 포함된다.
- 8/10 이후에 응답 DTO 초기값 정할 지 여부 결정 예정

* fix/member-1: 회원정보 각각의 필드값에 따른 수정을 가능하게 하자

- Set형태였던 hobbies, languages들을 null 값이 아닐 때에만 수정이 들어가며 null일 때에는 기존 값들이 들어가도록 함
- 기존의 /id API로 들어갔던 수정 메서드를 토큰 인증을 이용한 API로 수정함

* feat/dummy-1: 서버 재시작마다 자동으로 dummyData가 생성됨

- application.yml:
- defer-datasource-initialization:true:
- 데이터베이스 초기화를 지연시키는 옵션. JPA 엔티티를 데이터베이스 스키마에 매핑하기 전에 SQL 스크립트를 실행할 수 있게 하기 위함
- sql-init-mode:always:
- SQL 스크립트를 실행하게 하기 위함

- import.sql:
- 회원 5명, 게시글 각 게시판 별 5개씩 생성해놓음
- 이때 쿼리문에서는 비밀번호를 Encode할 수 없기 때문에 encode된 비밀번호를 넣어줌
- 게시글은 생성일 기준으로 나열되는 부분이 존재하기 때문에 CREATED 값을 NOW()로 넣어줌

- 추후 테스트 코드 활용을 위해 test 디렉토리의 application.yml에도 설정 값을 넣어줌

* feat/dummy-2: 게시글 관련 Dummy 데이터 추가 & 댓글 생성 시 알림 가도록

- 사용자 관련 Dummy 데이터 추가:
- 사용자 관련 language, hobby 데이터 추가

- 알림 토큰 Dummy 데이터 추가:
- 모든 사용자의 notification_token 추가

- 게시글 관련 Dummy 데이터 추가:
- 게시글 댓글 / 대댓글 데이터 추가
- 게시글/댓글 좋아요 추가

- CommentService:
- 본인이 작성한 게시글에 댓글이 달린다면 글쓴이에게 알림이 가도록
- 대댓글 작성이라면 게시글/댓글 글쓴이 모두에게 알림이 가도록

* feat/dummy-3: 어노테이션 되돌려놓기
- @manytomany의 기본이 FETCH.EAGER이라 착각함
- 불필요해진 옵션 값 취소

* feat/dummy-4 : 피드백 반영
- Dummy Data를 작성했던 application.yml 부분을 local로 빼서 각자의 local에 DummyData가 들어가도록 한다.
- 알림은 Username이 들어가도록 한다.
- 빠져있던 Expo 서버로 알림이 가는 요청을 서비스단에 추가해놓는다.

* feat/dummy-5 : 알림 서비스 코드 개선

- 알림 전송하는 부분에서 서비스별로 겹치는 코드가 많이 존재했다. 이를 NotificationService에 메서드(addNotifications)를 추가해 공통 코드를 줄임
- 주요 부분은 모두에게 알림이 전송되어야 하는 CONNECT를 제외하고 본인인지 여부를 검사한 후 아닌 경우에 알림을 전송함

- Notification 엔티티 수정 :
- 알림읽음 상태의 경우 엔티티를 삭제하기 때문에 무의미해진 isRead 필드값 삭제
  • Loading branch information
KooSuYeon authored Aug 8, 2024
1 parent 0ff1300 commit ec2c186
Show file tree
Hide file tree
Showing 13 changed files with 243 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class ReportController {
public ResponseEntity<ReportResponseDto> createDeclaration(
@RequestBody ReportRequestDto requestDto, Authentication auth) {

ReportResponseDto responseDto = reportService.createDeclaration(requestDto, auth.getName());
ReportResponseDto responseDto = reportService.createReport(requestDto, auth.getName());
return ResponseEntity.status(CREATED).body(responseDto);
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/dife/api/model/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class Member extends BaseTimeEntity {

@NotNull private String password = "";

private String username = "";
private String username = "Diver";

private String name = "";

Expand Down
2 changes: 0 additions & 2 deletions src/main/java/com/dife/api/model/Notification.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ public class Notification extends BaseTimeEntity {

private String message;

private Boolean isRead = false;

@ManyToOne
@JoinColumn(name = "notification_token_id")
@JsonIgnore
Expand Down
21 changes: 7 additions & 14 deletions src/main/java/com/dife/api/service/ChatService.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public class ChatService {
private final DisconnectHandler disconnectHandler;
private final NotificationHandler notificationHandler;
private final MemberService memberService;
private final NotificationService notificationService;
private final ModelMapper modelMapper;

public void sendMessage(ChatRequestDto dto, SimpMessageHeaderAccessor headerAccessor)
Expand Down Expand Up @@ -80,19 +81,10 @@ public void enter(ChatRequestDto dto, SimpMessageHeaderAccessor headerAccessor)
Set<Member> chatroomMembers = chatroom.getMembers();

for (Member chatroomMember : chatroomMembers) {
if (!Objects.equals(chatroomMember.getId(), member.getId())) {
List<NotificationToken> notificationTokens = chatroomMember.getNotificationTokens();

for (NotificationToken notificationToken : notificationTokens) {
Notification notification = new Notification();
notification.setNotificationToken(notificationToken);
notification.setType(NotificationType.CHAT);
notification.setMessage(
"WELCOME! 😊 " + chatroom.getName() + "방에 " + member.getEmail() + "님이 입장하셨습니다!");
notification.setIsRead(false);
notificationToken.getNotifications().add(notification);
}
}

String message =
"WELCOME! 😊 " + chatroom.getName() + "방에 " + member.getUsername() + "님이 입장하셨습니다!";
notificationService.addNotifications(chatroomMember, member, message, NotificationType.CHAT);
}

ChatRedisDto chatRedisDto = modelMapper.map(chat, ChatRedisDto.class);
Expand Down Expand Up @@ -129,8 +121,9 @@ public void chat(ChatRequestDto dto) throws JsonProcessingException {
message = message.substring(0, 30) + "...";
}
notification.setMessage(message);
notification.setIsRead(false);
notificationToken.getNotifications().add(notification);

notificationService.sendPushNotification(notificationToken.getPushToken(), message);
}
}
}
Expand Down
33 changes: 29 additions & 4 deletions src/main/java/com/dife/api/service/CommentService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
import com.dife.api.exception.CommentDuplicateException;
import com.dife.api.exception.MemberNotFoundException;
import com.dife.api.exception.PostNotFoundException;
import com.dife.api.model.Comment;
import com.dife.api.model.Member;
import com.dife.api.model.Post;
import com.dife.api.model.*;
import com.dife.api.model.dto.CommentCreateRequestDto;
import com.dife.api.model.dto.CommentResponseDto;
import com.dife.api.repository.CommentRepository;
Expand All @@ -17,6 +15,7 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -32,6 +31,8 @@ public class CommentService {
private final CommentRepository commentRepository;
private final LikeCommentRepository likeCommentRepository;

private final NotificationService notificationService;

@Transactional(readOnly = true)
public List<CommentResponseDto> getCommentsByPostId(Long postId, String memberEmail) {
Post post = postRepository.findById(postId).orElseThrow(PostNotFoundException::new);
Expand Down Expand Up @@ -71,8 +72,19 @@ public CommentResponseDto createComment(CommentCreateRequestDto requestDto, Stri
commentRepository.save(comment);

CommentResponseDto responseDto = modelMapper.map(comment, CommentResponseDto.class);
if (comment.getParentComment() != null)
if (comment.getParentComment() != null) {
responseDto.setParentComment(comment.getParentComment());
List<NotificationToken> parentCommentTokens =
comment.getParentComment().getWriter().getNotificationTokens();
String parentMessage =
"WOW!😆 " + comment.getWriter().getUsername() + "님이 회원님이 댓글을 남긴 게시글에 다른 댓글이 추가되었어요!";
addNotifications(parentCommentTokens, parentMessage, NotificationType.COMMUNITY);
}

List<NotificationToken> postTokens = post.getWriter().getNotificationTokens();
String postMessage = "WOW!😆 " + comment.getWriter().getUsername() + "님이 회원님의 게시글에 댓글이 추가되었어요!";
addNotifications(postTokens, postMessage, NotificationType.COMMUNITY);

return responseDto;
}

Expand All @@ -90,4 +102,17 @@ public CommentResponseDto getComment(Comment comment, Member member) {

return dto;
}

private void addNotifications(
List<NotificationToken> tokens, String message, NotificationType type) {
for (NotificationToken token : tokens) {
Notification notification = new Notification();
notification.setNotificationToken(token);
notification.setType(type);
notification.setMessage(message);
token.getNotifications().add(notification);

notificationService.sendPushNotification(token.getPushToken(), message);
}
}
}
29 changes: 11 additions & 18 deletions src/main/java/com/dife/api/service/ConnectService.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class ConnectService {

private final ModelMapper modelMapper;

private final NotificationService notificationService;

@Transactional(readOnly = true)
public List<ConnectResponseDto> getConnects(String currentMemberEmail) {
Member currentMember =
Expand Down Expand Up @@ -70,16 +72,9 @@ public ConnectResponseDto saveConnect(ConnectRequestDto dto, String currentMembe
connect.setStatus(ConnectStatus.PENDING);
connectRepository.save(connect);

List<NotificationToken> notificationTokens = toMember.getNotificationTokens();

for (NotificationToken notificationToken : notificationTokens) {
Notification notification = new Notification();
notification.setNotificationToken(notificationToken);
notification.setType(NotificationType.CONNECT);
notification.setMessage("Hi!🤝 " + currentMember.getEmail() + "님이 회원님과의 커넥트를 맺고 싶어해요!");
notification.setIsRead(false);
notificationToken.getNotifications().add(notification);
}
String message = "Hi!🤝 " + currentMember.getUsername() + "님이 회원님과의 커넥트를 맺고 싶어해요!";
notificationService.addNotifications(
toMember, currentMember, message, NotificationType.CONNECT);

return modelMapper.map(connect, ConnectResponseDto.class);
}
Expand Down Expand Up @@ -134,13 +129,11 @@ public boolean hasPendingConnect(Member fromMember, Member toMember) {

private void createNotifications(Member member, String otherMemberEmail) {
List<NotificationToken> notificationTokens = member.getNotificationTokens();
for (NotificationToken notificationToken : notificationTokens) {
Notification notification = new Notification();
notification.setNotificationToken(notificationToken);
notification.setType(NotificationType.CONNECT);
notification.setMessage("YEAH!🙌 " + otherMemberEmail + "님과의 커넥트가 성사되었어요!");
notification.setIsRead(false);
notificationToken.getNotifications().add(notification);
}

Member otherMember =
memberRepository.findByEmail(otherMemberEmail).orElseThrow(MemberNotFoundException::new);
String message = "YEAH!🙌 " + otherMember.getUsername() + "님과의 커넥트가 성사되었어요!";

notificationService.addNotifications(member, otherMember, message, NotificationType.CONNECT);
}
}
32 changes: 5 additions & 27 deletions src/main/java/com/dife/api/service/LikeService.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.dife.api.model.dto.PostResponseDto;
import com.dife.api.repository.*;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -30,6 +29,7 @@ public class LikeService {
private final LikeCommentRepository likeCommentRepository;

private final ModelMapper modelMapper;
private final NotificationService notificationService;

public List<PostResponseDto> getLikedPosts(String memberEmail) {
Member member =
Expand Down Expand Up @@ -67,19 +67,8 @@ public void createLikePost(Long postId, String memberEmail) {
likePostRepository.save(postLike);

Member writer = post.getWriter();

if (!Objects.equals(writer.getId(), member.getId())) {
List<NotificationToken> notificationTokens = writer.getNotificationTokens();

for (NotificationToken notificationToken : notificationTokens) {
Notification notification = new Notification();
notification.setNotificationToken(notificationToken);
notification.setType(NotificationType.COMMUNITY);
notification.setMessage("WOW!😆 " + member.getEmail() + "님이 회원님의 게시글을 좋아해요!");
notification.setIsRead(false);
notificationToken.getNotifications().add(notification);
}
}
String message = "WOW!😆 " + member.getUsername() + "님이 회원님의 게시글을 좋아해요!";
notificationService.addNotifications(writer, member, message, NotificationType.COMMUNITY);
}

public void deleteLikePost(LikeCreateRequestDto dto, String memberEmail) {
Expand Down Expand Up @@ -133,18 +122,7 @@ public void createLikeComment(Long commentId, String memberEmail) {
likeCommentRepository.save(likeComment);

Member writer = comment.getWriter();

if (!Objects.equals(writer.getId(), member.getId())) {
List<NotificationToken> notificationTokens = writer.getNotificationTokens();

for (NotificationToken notificationToken : notificationTokens) {
Notification notification = new Notification();
notification.setNotificationToken(notificationToken);
notification.setType(NotificationType.COMMUNITY);
notification.setMessage("WOW!😆 " + member.getEmail() + "님이 회원님의 댓글을 좋아해요!");
notification.setIsRead(false);
notificationToken.getNotifications().add(notification);
}
}
String message = "WOW!😆 " + member.getUsername() + "님이 회원님의 댓글을 좋아해요!";
notificationService.addNotifications(writer, member, message, NotificationType.COMMUNITY);
}
}
48 changes: 48 additions & 0 deletions src/main/java/com/dife/api/service/NotificationService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,27 @@
import static java.util.stream.Collectors.toList;

import com.dife.api.exception.MemberNotFoundException;
import com.dife.api.exception.NotificationException;
import com.dife.api.model.Member;
import com.dife.api.model.Notification;
import com.dife.api.model.NotificationToken;
import com.dife.api.model.NotificationType;
import com.dife.api.model.dto.NotificationResponseDto;
import com.dife.api.model.dto.NotificationTokenRequestDto;
import com.dife.api.model.dto.NotificationTokenResponseDto;
import com.dife.api.repository.MemberRepository;
import com.dife.api.repository.NotificationTokenRepository;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

@Service
@RequiredArgsConstructor
Expand Down Expand Up @@ -65,4 +73,44 @@ public List<NotificationResponseDto> getNotifications(String memberEmail) {
.map(n -> modelMapper.map(n, NotificationResponseDto.class))
.collect(toList());
}

public void sendPushNotification(String expoToken, String message) {
String expoPushUrl = "https://exp.host/--/api/v2/push/send";

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

Map<String, Object> body = new HashMap<>();
body.put("to", expoToken);
body.put("sound", "default");
body.put("body", message);

HttpEntity<Map<String, Object>> entity = new HttpEntity<>(body, headers);

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response =
restTemplate.exchange(expoPushUrl, HttpMethod.POST, entity, String.class);

if (response.getStatusCode() != HttpStatus.OK) throw new NotificationException();
}

public void addNotifications(
Member toMember, Member currentMember, String messageTemplate, NotificationType type) {
if (!Objects.equals(toMember.getId(), currentMember.getId())
&& type != NotificationType.CONNECT) {
List<NotificationToken> notificationTokens = currentMember.getNotificationTokens();

for (NotificationToken notificationToken : notificationTokens) {
Notification notification = new Notification();
notification.setNotificationToken(notificationToken);
notification.setType(type);

String message = String.format(messageTemplate, currentMember.getUsername());
notification.setMessage(message);
notificationToken.getNotifications().add(notification);

sendPushNotification(notificationToken.getPushToken(), message);
}
}
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/dife/api/service/ReportService.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class ReportService {

private final ModelMapper modelMapper;

public ReportResponseDto createDeclaration(ReportRequestDto requestDto, String memberEmail) {
public ReportResponseDto createReport(ReportRequestDto requestDto, String memberEmail) {

Member member =
memberRepository.findByEmail(memberEmail).orElseThrow(MemberNotFoundException::new);
Expand Down
8 changes: 8 additions & 0 deletions src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,16 @@ spring:
on-profile: local

jpa:
open-in-view: true
hibernate:
ddl-auto: create
defer-datasource-initialization: true


sql:
init:
mode: always
data-locations: classpath:import.sql

aws:
access-key: ${AWS_ACCESS_KEY_ID}
Expand Down
1 change: 0 additions & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
spring:
jpa:
database-platform: org.hibernate.dialect.MySQLDialect
open-in-view: false
show-sql: true
hibernate:
ddl-auto: update
Expand Down
Loading

0 comments on commit ec2c186

Please sign in to comment.