Skip to content

Commit

Permalink
Merge pull request #8 from Na-o-man/feature/#1/notification-api
Browse files Browse the repository at this point in the history
Feature/#1/notification api
  • Loading branch information
redblackblossom authored Jul 30, 2024
2 parents 33d8ff3 + 8763816 commit 2448de1
Show file tree
Hide file tree
Showing 19 changed files with 581 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ out/
.vscode/

application.yml
firebase_key.json
*.log
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ configurations {

repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}

dependencies {
Expand Down Expand Up @@ -50,6 +51,12 @@ dependencies {
testImplementation 'org.springframework.security:spring-security-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

//firebase
implementation 'com.google.firebase:firebase-admin:8.1.0'
//조사 처르를 쉽게 하기 위한 라이브러리
implementation 'com.github.josa-moa:josa-moa:1.0.3'

// AWS
// AWS, AWS S3
implementation platform("io.awspring.cloud:spring-cloud-aws-dependencies:3.0.0")
implementation 'io.awspring.cloud:spring-cloud-aws-starter-s3'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.umc.naoman.domain.notification.controller;

import com.umc.naoman.domain.member.entity.Member;
import com.umc.naoman.domain.notification.converter.NotificationConverter;
import com.umc.naoman.domain.notification.dto.NotificationRequest;
import com.umc.naoman.domain.notification.dto.NotificationResponse;
import com.umc.naoman.domain.notification.entity.Notification;
import com.umc.naoman.domain.notification.service.NotificationService;
import com.umc.naoman.global.result.ResultResponse;
import com.umc.naoman.global.result.code.NotificationResultCode;
import com.umc.naoman.global.security.annotation.LoginMember;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*;

import java.util.List;


@RestController
@RequiredArgsConstructor
@RequestMapping("/notifications")
public class NotificationController {
private final NotificationService notificationService;

@PostMapping("/token")
public ResultResponse<Void> registerFcmToken(@RequestBody NotificationRequest.FcmToken fcmToken,
@LoginMember Member member){

return ResultResponse.of(NotificationResultCode.REGISTER_FCM_TOKEN,null);
}

@GetMapping("/my")
public ResultResponse<NotificationResponse.PagedNotificationInfo> getNotifications(@LoginMember Member member,
@PageableDefault(sort = "createdAt", direction =Sort.Direction.DESC) Pageable pageable){
Page<Notification> notificationPage = notificationService.getNotificationList(member, pageable);
return ResultResponse.of(NotificationResultCode.GET_MY_NOTIFICATION,
NotificationConverter.toNotificationInfo(notificationPage));
}

@GetMapping("/unread")
public ResultResponse<NotificationResponse.UnreadNotification> getIsUnread(@LoginMember Member member){
List<Notification> notificationList = notificationService.isUnreadNotification(member);
return ResultResponse.of(NotificationResultCode.CHECK_MY_UNREAD_NOTIFICATION,
NotificationConverter.toUnreadNotification(notificationList));
}

@PostMapping("/acknowledgements")
public ResultResponse<NotificationResponse.NotificationAcknowledgeCount> setMyNotificationRead(@LoginMember Member member){
List<Notification> notificationList = notificationService.setMyNotificationRead(member);
return ResultResponse.of(NotificationResultCode.READ_ALL_MY_NOTIFICATION,
NotificationConverter.toNotificationAcknowledgedCount(notificationList));
}

@DeleteMapping("/{notificationId}")
public ResultResponse<NotificationResponse.NotificationAcknowledgeCount> deleteNotification(@PathVariable Long notificationId,
@LoginMember Member member){
long deletedCount = notificationService.deleteNotification(member,notificationId);
return ResultResponse.of(NotificationResultCode.DELETE_MY_NOTIFICATION,
NotificationConverter.toNotificationAcknowledgedCount(deletedCount));
}
@DeleteMapping
public ResultResponse<NotificationResponse.NotificationDeletedCount> deleteAllNotification(@LoginMember Member member){
long deletedCount = notificationService.deleteNotificationAll(member);
return ResultResponse.of(NotificationResultCode.DELETE_MY_NOTIFICATION,
NotificationConverter.toNotificationDeletedCount(deletedCount));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.umc.naoman.domain.notification.converter;

import com.umc.naoman.domain.member.entity.Member;
import com.umc.naoman.domain.notification.dto.NotificationRequest;
import com.umc.naoman.domain.notification.dto.NotificationResponse;
import com.umc.naoman.domain.notification.entity.DeviceToken;
import com.umc.naoman.domain.notification.entity.Notification;
import org.springframework.data.domain.Page;

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

public class NotificationConverter {

public static NotificationResponse.NotificationInfo notificationInfo(Notification notification){
return NotificationResponse.NotificationInfo.builder()
.body(notification.getMessage())
.createdAt(notification.getCreatedAt())
.isChecked(notification.isChecked())
.url(notification.makeNotificationInfoURL()) //다형성으로 각기 다른 알림이 적절한 URL 만들도록 오버라이딩.
.build();
}
public static NotificationResponse.PagedNotificationInfo toNotificationInfo(
Page<Notification> notificationList){
List<NotificationResponse.NotificationInfo> notificationInfoList
= notificationList.stream().map(NotificationConverter::notificationInfo).collect(Collectors.toList());

return NotificationResponse.PagedNotificationInfo.builder()
.isLast(notificationList.isLast())
.isFirst(notificationList.isFirst())
.totalPage(notificationList.getTotalPages())
.totalElements(notificationList.getTotalElements())
.notificationInfoList(notificationInfoList)
.build();
}

public static NotificationResponse.UnreadNotification toUnreadNotification(List<Notification> notificationList){
return NotificationResponse.UnreadNotification.builder()
.isUnread(!notificationList.isEmpty())
.build();
}

public static NotificationResponse.NotificationAcknowledgeCount toNotificationAcknowledgedCount(List<Notification> notificationList){
return NotificationResponse.NotificationAcknowledgeCount.builder()
.acknowledgedCount((long)notificationList.size())
.build();
}
public static NotificationResponse.NotificationAcknowledgeCount toNotificationAcknowledgedCount(Long updateCount){
return NotificationResponse.NotificationAcknowledgeCount.builder()
.acknowledgedCount(updateCount)
.build();
}

public static NotificationResponse.NotificationDeletedCount toNotificationDeletedCount(Long updateCount){
return NotificationResponse.NotificationDeletedCount.builder()
.deletedCount(updateCount)
.build();
}

public static DeviceToken toDeviceToken(Member member, NotificationRequest.FcmToken fcmToken){
return DeviceToken.builder()
.member(member)
.fcmToken(fcmToken.getToken())
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.umc.naoman.domain.notification.dto;

import lombok.Getter;

public class NotificationRequest {

@Getter
public static class FcmToken {
String token;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.umc.naoman.domain.notification.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;

public class NotificationResponse {
@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class PagedNotificationInfo {
List<NotificationInfo> notificationInfoList;
Integer totalPage;
Long totalElements;
Boolean isFirst;
Boolean isLast;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class NotificationInfo {
String body;
Boolean isChecked;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime createdAt;
String url;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class UnreadNotification {
Boolean isUnread;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class NotificationAcknowledgeCount {
Long acknowledgedCount;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class NotificationDeletedCount {
Long deletedCount;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.umc.naoman.domain.notification.entity;

import com.umc.naoman.domain.agenda.entity.Agenda;
import com.umc.naoman.domain.member.entity.Member;
import com.umc.naoman.domain.notification.service.JosamoaSingleton;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
Expand All @@ -24,4 +26,39 @@ public class AgendaNotification extends Notification {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "agenda_id")
private Agenda agenda;


/*
*[그룹명]의 [유저명]이 [안경명] 투표를 열었습니다.
*/
@Override
public void postMessage(){
StringBuilder sb = new StringBuilder();
sb.append(agenda.getShareGroup().getName());
sb.append("의 ");
sb.append(JosamoaSingleton.setJosa(getActor().getName(),"이가"));
sb.append(" ");
sb.append(agenda.getTitle());
sb.append(" 투표를 열었습니다.");
message = sb.toString();
}

@Override
public Notification makeOtherNotification(Member member){
return AgendaNotification.builder()
.id(this.getId())
.message(this.getMessage())
.member(member)
.isChecked(false)
.actor(this.getActor())
.agenda(this.getAgenda())
.build();
}

@Override
public String makeNotificationInfoURL() {
//해당 아젠다로 이동
// todo 아젠다 컨틀롤러 만들어 지면 MvcUriComponentsBuilder 로 리팩토링 예정
return "/agendas/" + agenda.getId();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.umc.naoman.domain.notification.entity;

import com.umc.naoman.domain.member.entity.Member;
import com.umc.naoman.domain.notification.service.JosamoaSingleton;
import com.umc.naoman.domain.shareGroup.entity.ShareGroup;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.SQLRestriction;

@Entity
@Table(name = "delete_photo_notifications")
@SQLRestriction("deleted_at is NULL")
@Getter
@SuperBuilder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class DeletePhotoNotification extends Notification {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "share_group_id")
private ShareGroup shareGroup;
@Column(name = "photo_count", nullable = false)
private int photoCount;

/*
*[유저명]이 [그룹명]의 사진 [삭제 장수]장을 삭제했습니다.
*/
@Override
public void postMessage(){
StringBuilder sb = new StringBuilder();
sb.append(JosamoaSingleton.setJosa(getActor().getName(),"이가"));
sb.append(" ");
sb.append(shareGroup.getName());
sb.append("의 사진 ");
sb.append(photoCount);
sb.append("장을 삭제했습니다.");
message = sb.toString();
}
@Override
public Notification makeOtherNotification(Member member){
return DeletePhotoNotification.builder()
.id(this.getId())
.message(this.getMessage())
.member(member)
.isChecked(false)
.actor(this.getActor())
.shareGroup(getShareGroup())
.photoCount(getPhotoCount())
.build();
}

@Override
public String makeNotificationInfoURL() {
//사진 삭제 알람 클릭 하면 무반응
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@
@SuperBuilder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Notification {
public abstract class Notification {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "notification_id")
private Long id;
@Column(nullable = false)
private String message;
protected String message;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;
Expand All @@ -52,8 +52,17 @@ public class Notification {
private LocalDateTime createdAt;
@Column(name = "deleted_at")
private LocalDateTime deletedAt;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "actor_id")
private Member actor;

public void delete() {
this.deletedAt = LocalDateTime.now();
}
public abstract void postMessage();
public abstract Notification makeOtherNotification(Member member);
public abstract String makeNotificationInfoURL();
public void notificationAcknowledge(boolean isChecked){
this.isChecked = isChecked;
}
}
Loading

0 comments on commit 2448de1

Please sign in to comment.