Skip to content

Commit

Permalink
[BE] 피드백 완료 알람 기능 구현(#771) (#772)
Browse files Browse the repository at this point in the history
* feat: Alarm 인터페이스 구현

* feat: ServerToUserAlarm 구현체 생성

* refactor: 기존 UserToUserAlarm을 Alarm 구현체로 변경

* feat: 매칭 결과 알람 생성 로직 구현

* feat: 알람 자동 생성 로직 구현 (trigger: 매칭 완료)

* test: 테스트 작성

* refactor: 메서드 분리

* feat: 피드백 완료 알람 타입 추가

* feat: 피드백 완료 알람 기능 구현

* test: 피드백 작성 알람 생성 테스트

* test: 개발/소셜 피드백 테스트 중복 부분 `@BeforeEach` 로 처리

* fix: 깨지는 CI 해결

---------

Co-authored-by: ashsty <[email protected]>
  • Loading branch information
github-actions[bot] and ashsty authored Nov 21, 2024
1 parent 00cf45c commit 903a722
Show file tree
Hide file tree
Showing 31 changed files with 716 additions and 264 deletions.
22 changes: 22 additions & 0 deletions backend/src/main/java/corea/alarm/domain/Alarm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package corea.alarm.domain;

import corea.member.domain.Member;

public interface Alarm {

boolean isStatus(boolean status);

boolean isNotReceiver(Member member);

void read();

String getActionType();

Long getId();

Long getActorId();

Long getInteractionId();

Long getReceiverId();
}
3 changes: 3 additions & 0 deletions backend/src/main/java/corea/alarm/domain/AlarmActionType.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@
public enum AlarmActionType {
REVIEW_COMPLETE,
REVIEW_URGE,
MATCH_COMPLETE,
MATCH_FAIL,
FEEDBACK_CREATED,
}
3 changes: 2 additions & 1 deletion backend/src/main/java/corea/alarm/domain/AlarmType.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

public enum AlarmType {
// 유저간 상호작용으로 인한 알람
USER;
USER,
SERVER;

public static AlarmType from(String value) {
return AlarmType.valueOf(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
import java.util.Set;
import java.util.stream.Collectors;

public record UserAlarmsByActionType(Map<AlarmActionType, List<UserToUserAlarm>> data) {
public record AlarmsByActionType(Map<AlarmActionType, List<Alarm>> data) {

public Set<Long> getActorIds() {
return data.values()
.stream()
.flatMap(Collection::stream)
.map(UserToUserAlarm::getActorId)
.map(Alarm::getActorId)
.collect(Collectors.toSet());
}

Expand All @@ -20,11 +21,11 @@ public Set<Long> getRoomIds() {
.stream()
.flatMap(Collection::stream)
//.filter(alarm -> alarm.getAlarmActionType() == AlarmActionType.REVIEW_COMPLETE)
.map(UserToUserAlarm::getInteractionId)
.map(Alarm::getInteractionId)
.collect(Collectors.toSet());
}

public List<UserToUserAlarm> getList() {
public List<Alarm> getList() {
return data.values()
.stream()
.flatMap(Collection::stream)
Expand Down
60 changes: 60 additions & 0 deletions backend/src/main/java/corea/alarm/domain/ServerToUserAlarm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package corea.alarm.domain;

import corea.global.BaseTimeEntity;
import corea.member.domain.Member;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import static jakarta.persistence.GenerationType.IDENTITY;

@Entity
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class ServerToUserAlarm extends BaseTimeEntity implements Alarm {

@Id
@GeneratedValue(strategy = IDENTITY)
private Long id;

@Enumerated(EnumType.STRING)
private AlarmActionType alarmActionType;

private Long receiverId;

private Long interactionId;

private boolean isRead;

public ServerToUserAlarm(AlarmActionType alarmActionType, long receiverId, long interactionId, boolean isRead) {
this(null, alarmActionType, receiverId, interactionId, isRead);
}

@Override
public boolean isStatus(boolean status) {
return isRead == status;
}

@Override
public String getActionType() {
return alarmActionType.name();
}

@Override
public Long getActorId() {
return null;
}

@Override
public boolean isNotReceiver(Member member) {
return !receiverId.equals(member.getId());
}

@Override
public void read() {
isRead = true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package corea.alarm.domain;

import corea.alarm.repository.ServerToUserAlarmRepository;
import corea.exception.CoreaException;
import corea.exception.ExceptionType;
import corea.global.annotation.Reader;
import corea.member.domain.Member;
import lombok.RequiredArgsConstructor;

import java.util.EnumMap;
import java.util.stream.Collectors;

@Reader
@RequiredArgsConstructor
public class ServerToUserAlarmReader {

private final ServerToUserAlarmRepository serverToUserAlarmRepository;

public long countReceivedAlarm(Member member, boolean isRead) {
return serverToUserAlarmRepository.findAllByReceiverId(member.getId())
.stream()
.filter(alarm -> alarm.isStatus(isRead))
.count();
}

public ServerToUserAlarm find(long actionId) {
return serverToUserAlarmRepository.findById(actionId)
.orElseThrow(() -> new CoreaException(ExceptionType.NOT_RECEIVED_ALARM));
}

public AlarmsByActionType findAllByReceiver(Member member) {
return new AlarmsByActionType(serverToUserAlarmRepository.findAllByReceiverId(member.getId())
.stream()
.collect(Collectors.groupingBy(
ServerToUserAlarm::getAlarmActionType,
() -> new EnumMap<>(AlarmActionType.class),
Collectors.toList()
)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package corea.alarm.domain;

import corea.alarm.repository.ServerToUserAlarmRepository;
import corea.exception.CoreaException;
import corea.exception.ExceptionType;
import corea.global.annotation.Writer;
import corea.member.domain.Member;
import lombok.RequiredArgsConstructor;

@Writer
@RequiredArgsConstructor
public class ServerToUserAlarmWriter {

private final ServerToUserAlarmRepository serverToUserAlarmRepository;

public ServerToUserAlarm create(ServerToUserAlarm serverToUserAlarm) {
return serverToUserAlarmRepository.save(serverToUserAlarm);
}

public ServerToUserAlarm check(Member member, ServerToUserAlarm serverToUserAlarm) {
if (serverToUserAlarm.isNotReceiver(member)) {
throw new CoreaException(ExceptionType.NOT_RECEIVED_ALARM);
}
serverToUserAlarm.read();
return serverToUserAlarm;
}
}
14 changes: 9 additions & 5 deletions backend/src/main/java/corea/alarm/domain/UserToUserAlarm.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class UserToUserAlarm extends BaseTimeEntity {
public class UserToUserAlarm extends BaseTimeEntity implements Alarm {

@Id
@GeneratedValue(strategy = IDENTITY)
Expand All @@ -40,23 +40,27 @@ public UserToUserAlarm(AlarmActionType alarmActionType, long actorId, long recei
this(null, alarmActionType, actorId, receiverId, interactionId, isRead);
}

public boolean isUrgeAlarm() {
return alarmActionType == AlarmActionType.REVIEW_URGE;
}

@Override
public boolean isStatus(boolean status) {
return isRead == status;
}

@Override
public String getActionType() {
return alarmActionType.name();
}

@Override
public boolean isNotReceiver(Member member) {
return !receiverId.equals(member.getId());
}

@Override
public void read() {
isRead = true;
}

public boolean isUrgeAlarm() {
return alarmActionType == AlarmActionType.REVIEW_URGE;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package corea.alarm.domain;

import corea.alarm.repository.UserToUserAlarmRepository;
import corea.exception.CoreaException;
import corea.exception.ExceptionType;
import corea.global.annotation.Reader;
Expand Down Expand Up @@ -28,8 +29,8 @@ public UserToUserAlarm find(long actionId) {
.orElseThrow(() -> new CoreaException(ExceptionType.NOT_RECEIVED_ALARM));
}

public UserAlarmsByActionType findAllByReceiver(Member member) {
return new UserAlarmsByActionType(userToUserAlarmRepository.findAllByReceiverId(member.getId())
public AlarmsByActionType findAllByReceiver(Member member) {
return new AlarmsByActionType(userToUserAlarmRepository.findAllByReceiverId(member.getId())
.stream()
.collect(Collectors.groupingBy(
UserToUserAlarm::getAlarmActionType,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package corea.alarm.domain;

import corea.alarm.repository.UserToUserAlarmRepository;
import corea.exception.CoreaException;
import corea.exception.ExceptionType;
import corea.global.annotation.Writer;
Expand All @@ -15,7 +16,7 @@ public class UserToUserAlarmWriter {
public UserToUserAlarm create(UserToUserAlarm userToUserAlarm) {
return userToUserAlarmRepository.save(userToUserAlarm);
}

public UserToUserAlarm check(Member member, UserToUserAlarm userToUserAlarm) {
if (userToUserAlarm.isNotReceiver(member)) {
throw new CoreaException(ExceptionType.NOT_RECEIVED_ALARM);
Expand Down
11 changes: 9 additions & 2 deletions backend/src/main/java/corea/alarm/dto/AlarmResponse.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package corea.alarm.dto;

import corea.alarm.domain.AlarmType;
import corea.alarm.domain.ServerToUserAlarm;
import corea.alarm.domain.UserToUserAlarm;
import corea.member.domain.Member;
import corea.room.domain.Room;
Expand Down Expand Up @@ -31,7 +32,13 @@ public record AlarmResponse(
String alarmType
) {

public static AlarmResponse from(UserToUserAlarm alarm, Member member, Room room) {
return new AlarmResponse(alarm.getId(), alarm.getActionType(), MemberResponse.from(member), InteractionResponse.from(room), alarm.isRead(), alarm.getCreateAt(), AlarmType.USER.name());
public static AlarmResponse of(UserToUserAlarm alarm, Member member, Room room) {
return new AlarmResponse(alarm.getId(), alarm.getActionType(), MemberResponse.from(member),
InteractionResponse.from(room), alarm.isRead(), alarm.getCreateAt(), AlarmType.USER.name());
}

public static AlarmResponse of(ServerToUserAlarm alarm, Room room) {
return new AlarmResponse(alarm.getId(), alarm.getActionType(), null,
InteractionResponse.from(room), alarm.isRead(), alarm.getCreateAt(), AlarmType.SERVER.name());
}
}
18 changes: 15 additions & 3 deletions backend/src/main/java/corea/alarm/dto/AlarmResponses.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package corea.alarm.dto;

import corea.alarm.domain.Alarm;
import corea.alarm.domain.ServerToUserAlarm;
import corea.alarm.domain.UserToUserAlarm;
import corea.exception.CoreaException;
import corea.exception.ExceptionType;
import corea.member.domain.Member;
import corea.room.domain.Room;
import io.swagger.v3.oas.annotations.media.Schema;
Expand All @@ -13,10 +17,18 @@ public record AlarmResponses(
@Schema(description = "알림 리스트")
List<AlarmResponse> data) {

public static AlarmResponses from(List<UserToUserAlarm> responses, Map<Long, Member> members, Map<Long, Room> rooms) {
public static AlarmResponses of(List<Alarm> alarms, Map<Long, Member> members, Map<Long, Room> userAlarmRooms, Map<Long, Room> serverAlarmRooms) {
//@formatter:off
return new AlarmResponses(responses.stream()
.map(alarm -> AlarmResponse.from(alarm, members.get(alarm.getActorId()), rooms.get(alarm.getInteractionId())))
return new AlarmResponses(alarms.stream()
.map(alarm -> {
if (alarm instanceof UserToUserAlarm userAlarm) {
return AlarmResponse.of(userAlarm, members.get(userAlarm.getActorId()), userAlarmRooms.get(userAlarm.getInteractionId()));
}
if (alarm instanceof ServerToUserAlarm serverAlarm){
return AlarmResponse.of(serverAlarm, serverAlarmRooms.get(serverAlarm.getInteractionId()));
}
throw new CoreaException(ExceptionType.UNDEFINED_ALARM_TYPE);
})
.sorted(Comparator.comparing(AlarmResponse::createAt).reversed())
.toList());
//@formatter:on
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package corea.alarm.dto;

import corea.alarm.domain.AlarmActionType;
import corea.alarm.domain.ServerToUserAlarm;

public record CreateServerToUserAlarmInput(AlarmActionType alarmType,
long receiverId,
long interactionId) {

public ServerToUserAlarm toEntity() {
return new ServerToUserAlarm(
alarmType,
receiverId,
interactionId,
false
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package corea.alarm.repository;

import corea.alarm.domain.ServerToUserAlarm;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface ServerToUserAlarmRepository extends JpaRepository<ServerToUserAlarm, Long> {

List<ServerToUserAlarm> findAllByReceiverId(long receiverId);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package corea.alarm.domain;
package corea.alarm.repository;

import corea.alarm.domain.UserToUserAlarm;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
Expand Down
Loading

0 comments on commit 903a722

Please sign in to comment.